Getting last data from child process in Leopard
Getting last data from child process in Leopard
- Subject: Getting last data from child process in Leopard
- From: Ingemar Ragnemalm <email@hidden>
- Date: Mon, 24 Mar 2008 20:44:45 +0100
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:
This email sent to email@hidden