Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Getting last data from child process in Leopard




On Mar 24, 2008, at 12:44 PM, Ingemar Ragnemalm wrote:

I am new to the list, so I apologize if this is common knowledge. I have searched the archives (and Google) and come up with nothing useful.

I have an application which works nicely in Tiger, but has some major problems in Leopard. I spawn sub-processes with forkpty, and communicate with read and write (the standard Unix calls). I use forkpty in order to get unbuffered data, to avoid deadlocks and to deliver data promptly to the user.

Under Tiger, this works very well. Leopard behaves very differently.

This is because your code is very racy. Signals can interrupt system calls, including read(2), and what's happening is that your SIGCHLD is causing the read to be interrupted and miss data. 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). 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.


Here is a diff to your code which will make it work less by luck, as it did on Tiger, and more by design. I'm sure that this is also just sample code and not something you're trying to really do in production since looping on a non-blocking fd waiting for input is very inefficient. That's what poll(2) is for.

- Jordan

--- forkpty.c.orig	2008-03-25 15:35:16.000000000 -0700
+++ forkpty.c	2008-03-25 15:34:22.000000000 -0700
@@ -57,6 +57,7 @@
     // Wait for result
   while (!done)
   {
+try_again:
       i = 255; // buffer size
       i = read(pty, s, i);
       if (i>0)
@@ -64,8 +65,11 @@
           s[i] = 0;
           printf("Read %d: <%s>\n", i, s);
       }
-      else
+      else {
           printf("*");
+	  if (errno == EAGAIN)
+		goto try_again;
+      }
       sleep(1);
   }


% uname -a
Darwin watusi9.apple.com 9.2.2 Darwin Kernel Version 9.2.2: Tue Mar 4 21:23:43 PST 2008; root:xnu-1228.4.31~1/RELEASE_PPC Power Macintosh



_______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-dev/email@hidden

This email sent to email@hidden
References: 
 >Getting last data from child process in Leopard (From: Ingemar Ragnemalm <email@hidden>)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.