Re: Getting last data from child process in Leopard
site_archiver@lists.apple.com Delivered-To: darwin-dev@lists.apple.com On Mar 25, 2008, at 6:39 PM, Steve Checkoway wrote: - Jordan _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-dev mailing list (Darwin-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-dev/site_archiver%40lists.appl... Jordan K. Hubbard wrote: Your signal handler ("deadbeef") also should not be attempting to read from the pty since there are a lot of operations not considered safe from signal handlers (your results are guaranteed to be "undefined", if not outright incorrect). According to the man page for sigaction(2), read(2) is one of the base interfaces that is "either reentrant or not interruptible by signals and are async-signal safe [and therefore] applications may invoke them, without restriction, from signal-catching functions. I chose my words fairly carefully in saying "there are a lot of operations not considered safe" and I didn't call read(2) specifically unsafe since, technically, it is. However, there's a difference between the letter of the law and best practices, and best practices have always been to do as little as humanly possible from a signal handler (setting a flag, for example). Given that, I'll always recommend that people not try to be clever in their signal handlers, particularly where file I/O is concerned given that even with async safety in the calls, it's impossible to know _when_ the file operation will take place and races abound. Programmers are rarely as clever as they think they are, so it's better to advise them to stay away from the fringes of what is possible, but unwise, to do with the Unix APIs. 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). If you try his example checking for EINTR on Leopard, at least, you'll still fail to catch that last "BYE" (try it). 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... This email sent to site_archiver@lists.apple.com
participants (1)
-
Jordan K. Hubbard