Mailing Lists: Apple Mailing Lists

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

Getting last data from child process in Leopard




Dear list,

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.

Tiger is actually very friendly; when the sub-process terminates, it seems to keep it open until I have read all data from it, and only when fully drained it really terminates. Under Leopard, it dies if I call waitpid(), which is legal. No problem, I keep reading until I get nothing, and then I check with waitpid().

This seems to work if I have a tight loop polling the fd, but if I don't poll all the time, any data sent close to termination is lost.

OK, I thought, so I catch the SIGCHLD signal to know when it terminates? No go, when I get the signal, the data is already trashed, that is, I get nothing from read.

Here is an example program:

-------------
#include <stdio.h>
#include <stdlib.h>
#include <util.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/filio.h>
#include <sys/errno.h>

void hello()
{
   printf("hello!\n");
   sleep(2);
   printf("there!\n");
   sleep(2);
   printf("BYE!\n");
}

int pty;
int done = 0;

void deadbeef(int a)
{
int i;
char name[255];
i = 100;
i = read(pty, name, i);
if (i > 0) printf("Signal handler read %d %s\n", i, name);
else printf("Signal handler read nothing\n");


   printf("aaarrrggh!\n");
   done = 1;
}

main()
{
int pid, i, err;
int mypid, ohyes;
char s[255];
if (( pid = forkpty( &(pty), NULL, NULL, NULL) ) < 0)
{ // Failure
printf( "Forking error\n");
exit(-1);
}
if (0 == pid)
{ // Slave - child process
hello();
exit( 0);
}
// Otherwise parent process
int flags;
// set file to non-blocking */
flags = fcntl(pty, F_GETFL, 0);
if (0 != fcntl(pty, F_SETFL, flags | O_NONBLOCK))
printf( "fcntl error");
if( SIG_ERR == signal( SIGCHLD, deadbeef))
printf( "SIGCHLD error");
// Wait for result
while (!done)
{
i = 255; // buffer size
i = read(pty, s, i);
if (i>0)
{
s[i] = 0;
printf("Read %d: <%s>\n", i, s);
}
else
printf("*");
sleep(1);
}
exit(0);
}
------------


Under Tiger, it seems to work pretty well. Under Leopard, the "bye" line is always lost!

Something significant has changed in Leopard! How do I get the last data from the child process when it terminates?


/Ingemar

_______________________________________________
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


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.