Re: [Fwd: Re: Getting last data from child process in Leopard]
Re: [Fwd: Re: Getting last data from child process in Leopard]
- Subject: Re: [Fwd: Re: Getting last data from child process in Leopard]
- From: Terry Lambert <email@hidden>
- Date: Tue, 25 Mar 2008 20:33:00 -0700
EINTR is possible, but tends to be rare. This is because signals are
implemented using Mach ASTs, which means that even if you send a
signal, if the operation in progress can be completed prior to running
up to the user/kernel boundary, then it will be. The AST only
triggers the signal trampoline at that point.
If it successfully completes with no blocking, then an EINTR will not
be returned, and instead after the signal handler (if any) or the
default action (if it is to terminate the program) have had an
opportunity to return, then the system call will complete successfully
instead.
In the case of a non-blocking fd, the request will almost always be
able to complete without hitting an operation that will trigger an
EINTR return.
You should probably look for both the EAGAIN and EINTR, particularly
if you you plan on your code being portable to other UNIX platforms.
-- Terry
On Mar 25, 2008, at 7:22 PM, Steve Checkoway <email@hidden> wrote:
Oops, didn't mean to send this off list.
Jordan K. Hubbard wrote:
On Mar 25, 2008, at 6:39 PM, Steve Checkoway wrote:
Jordan K. Hubbard wrote:
The right thing to do is check for EAGAIN in your read() loop and
go back and retry for the data in that case. Given that you're
using O_NONBLOCK, it's even more important to make sure you
handle all the async event cases.
Do you mean EINTR? "If a signal is caught during the systems calls
listed below [including read(2)], the call may be forced to
terminate with the error EINTR, the call may return with a data
transfer shorter than requested, or the call may be restarted."
Nope, I do mean EAGAIN. In the context of non-blocking I/O, it's
precisely what he needs to check for in this case, at least on
MacOSX (other Unix variants may return EINTR instead - this is one
of the grey areas of Unix behavior).
Ah, I misunderstood. I thought you were saying he needed to check for
EAGAIN because signals were interrupting the system call since that's
what you were talking about in the sentences before and you only
mentioned the nonblocking afterward. Of course he needed to check for
EAGAIN because of the nonblocking. (I'm still not really sure why he
wants that there in the first place though.)
If you try his example checking for EINTR on Leopard, at least,
you'll still fail to catch that last "BYE" (try it).
Sure.
I didn't manage to get the signal to interrupt the read(), but
that's probably because of the nonblocking IO. I'm not sure why
you think you need unbuffered IO to avoid deadlocks or to deliver
data quickly. As you probably noticed, printf() on the child side
was buffering anyway.
Try shortening the sleep(2) intervals. You can get the race
condition to happen fairly easily - I didn't express that change in
my diffs since I didn't think it was relevant to the advice I was
trying to give him...
I didn't manage to get read() to be interrupted even when I removed
the
sleep call in the parent. I also didn't get it when I changed from
nonblocking to blocking, but maybe it is just restarting the calls
(I'm
not seeing the default restart behavior listed in the man page). That
said, I don't doubt that the signal can interrupt it. I just don't
think
that was his problem since he said it happened every time and I can't
get it to happen even once (in my oh-so-scientific sample size of
about
15 runs).
--
Steve Checkoway
--
Steve Checkoway
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden