[comp.unix.questions] signals interrupting IPC functions

mike@ISIDAPS5.UUCP (Mike Maloney) (09/23/88)

When a call to msgrcv terminates because of the arrival of a signal,
is it possible that a message on the queue could be lost?  I want
to be able to read a message queue and process messages as soon as
they arrive, or timeout and do other stuff after 3 seconds:

	signal(SIG_ALARM, timeout);
	alarm(3);

	s = msgrcv(id, buf, size, 0, 0);
	if (s == -1)
	{	if (errno == EINTR)
			Timeout happened....do stuff.
		else
			Some other dasterdly error occurred.
	}
	else /* Timeout did not occur. */
	{	alarm(0);	/* Cancel alarm. */
		...process message that arrived.
	}

The code for the 'timeout' function does absolutely nothing.  Just
the fact that the signal was caught should cause msgrcv to return.

I'm worried about the alarm clobbering msgrcv() and causing it to
drop a message.  Does msgrcv guard against this?

Please confirm my fears or set my mind at ease.
-- 
Mike Maloney				"That's like saying 'if we had
Integral Systems, Inc.			 eggs we could have bacon and eggs
Lanham, Maryland 20706			 if we had bacon'" - Sid
(301) 731-4233 ext. 165

dave@micropen (David F. Carlson) (09/23/88)

In article <216@ISIDAPS5.UUCP>, mike@ISIDAPS5.UUCP (Mike Maloney) writes:
> When a call to msgrcv terminates because of the arrival of a signal,
> is it possible that a message on the queue could be lost?  I want
> to be able to read a message queue and process messages as soon as
> they arrive, or timeout and do other stuff after 3 seconds:
> 	s = msgrcv(id, buf, size, 0, 0);
> 	{	if (errno == EINTR)
> 
> Please confirm my fears or set my mind at ease.
> Mike Maloney				"That's like saying 'if we had

RTFM:  signal(2):
"When a signal to be caught occurs during read(2), a write(2), an open(2),
an ioctl(2) or system call to a slow device, ... during pause(2) or wait(2),
... the system call may return -1 to the calling process with errno set
to EINTR."

No mention of msgrcv(2) at all.  I believe since it is not mentioned, it
is guaranteed not to occur.



-- 
David F. Carlson, Micropen, Inc.
micropen!dave@ee.rochester.edu

"The faster I go, the behinder I get." --Lewis Carroll

quan@hplabsb.UUCP (Suu Quan) (09/24/88)

In article <216@ISIDAPS5.UUCP>, mike@ISIDAPS5.UUCP (Mike Maloney) writes:
> When a call to msgrcv terminates because of the arrival of a signal,
> is it possible that a message on the queue could be lost?  I want
> to be able to read a message queue and process messages as soon as
> they arrive, or timeout and do other stuff after 3 seconds:
> 
> 	signal(SIG_ALARM, timeout);
> 	alarm(3);
> 
> 	s = msgrcv(id, buf, size, 0, 0);
> 	if (s == -1)
> 	{	if (errno == EINTR)
> 			Timeout happened....do stuff.
> 		else
> 			Some other dasterdly error occurred.
> 	}
> 	else /* Timeout did not occur. */
> 	{	alarm(0);	/* Cancel alarm. */
> 		...process message that arrived.
> 	}
> 
> The code for the 'timeout' function does absolutely nothing.  Just
> the fact that the signal was caught should cause msgrcv to return.
> 
> I'm worried about the alarm clobbering msgrcv() and causing it to
> drop a message.  Does msgrcv guard against this?
> 
	msgrcv() -I don't think - is not an atomic operation. It may
be signaled in the middle of a reception, and you may loose messages.
I suggest the following pseudo code for your timeout routine.

timeout(signo, code, scp)
int signo, code;
register struct sigcontext *scp;
{ if (incoming queue has no-zero message length)
	if (scp != NULL) scp->syscall_action = SIG_RESTART;
}

	This should restart your msgrecv() if there is something in it
and disrupt msgrecv() if there is none.

jfh@rpp386.Dallas.TX.US (The Beach Bum) (09/25/88)

In article <548@micropen> dave@micropen (David F. Carlson) writes:
} In article <216@ISIDAPS5.UUCP>, mike@ISIDAPS5.UUCP (Mike Maloney) writes:
} > When a call to msgrcv terminates because of the arrival of a signal,
} > is it possible that a message on the queue could be lost?
} 
} RTFM:  signal(2):
} "When a signal to be caught occurs during read(2), a write(2), an open(2),
} an ioctl(2) or system call to a slow device, ... during pause(2) or wait(2),
} ... the system call may return -1 to the calling process with errno set
} to EINTR."
} 
} No mention of msgrcv(2) at all.  I believe since it is not mentioned, it
} is guaranteed not to occur.

incorrect.  the page for msgrcv(2) states that if IPC_NOWAIT is false in
the call to msgrcv() and a signal which is set to be received occurs, then
msgrcv() returns -1 and errno == EINTR.

this behavior is going to be true, in general, of all system calls which
can be expected to block for more than a brief period of time.  the only
requirement that a system call be interuptable is that it does not sleep
at less than PZERO.

to answer david's question - not likely unless there is a race in the
kernel i've never seen posted to the net.  the two situations involve
either the process sending itself a signal [ SIGALRM being the only one
it can ] or some other process sending it a signal.

some other process can only send it a signal if no message is ready to be
read [ more or less ], so the message, which isn't being processed
because it
doesn't exist, can't be lost.

the only signal a process can send itself while blocked in a system call
is SIGALRM.  if the process is blocked at the moment, no big deal, same
situation as above.  otherwise, the exact result depends on the scheduler
and how it works.  but generally i'd say the answer is no.
-- 
John F. Haugh II (jfh@rpp386.Dallas.TX.US)                   HASA, "S" Division

      "Why waste negative entropy on comments, when you could use the same
                   entropy to create bugs instead?" -- Steve Elias