This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Problem with fork/exec/setsid/fgets (was: cygwin_attach_handle_to_fd())


Christopher Faylor wrote:

> As usual, "loads of grief" is not an adequate bug report.  You probably
> don't think you're providing a bug report, but you are.  Cygwin is supposed
> to be a UNIX emulation package.  If you can't use fork/exec for some reason
> then that's a serious problem.
>
> >I've switched to using CreateProcess() and the grief goes away (except
> >for this little problem I'm having here).  I'll try some new things
> >here and post my findings..

OKAY you're right.  rather than try to write a whole new 250 lines of code using CreateProcess() to get around
a single problem, I should really get to work on finding the fork/exec problem in the first place.

Here goes:

I reduced my code to the smallest program possible with the same functionality.  here is the test case:
A program which uses fork(), exec(), AND fgets() and setsid(), will hang after two children have been produced.

Run the attached program and press return twice.  you will see the output of "dir.exe" twice.  press return again.  now you get
nothing.  commenting out the "#define TEST_USE_FGETS" and / or "#define TEST_USE_SETSID" will allow the program
to run without error.  (note that when not defining TEST_USE_FGETS that the program just creates one child at a time forever)


I am running the latest cygwin (1.3.2) on an PIII 400Mhz WinNTsp6a box.  The workaround here is to quit using setsid(), but that does
have some implications...

Any help would be greatly appreciated.  I've looked at the cygwin source code but do not feel I would be capable of coming up with
and accurate diagnosis of the cygwin internals..

Thanks,
Craig Nelson, Cameo Systems Inc.

#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>

#define TEST_USE_FGETS
#define TEST_USE_SETSID

/*
  Using:	cygwin 1.3.2
Compile:	gcc -o kk kk.c
    Run:	kk.exe
		<press enter a 3 or more times>
   Note:	You dont need to press enter when TEST_USE_FGETS is not defined.  
		The program will loop forever.

Problem:
		-Typical fork/exec program hangs when using setsid() AND fgets():
		 Program loops twice then fgets() never returns.

Theory:		-Program heap is somehow corrupted via use of setsid, fgets().
*/


void kk_sig_handler (void)
{
	/* Grab the exit status of a child process. */
	/* In this test program, we just throw it out anyway */
	int hpid,es;

	hpid=-2;
	while (hpid<=0 && hpid!=-1) hpid=waitpid(-1,&es,WNOHANG);
}

int main (int argc, char **argv)
{
	char buf[64];
	char **av;
	int revpid;
	struct sigaction act;

	memset (&act,0,sizeof(struct sigaction));
	act.sa_handler=(void(*)(int))kk_sig_handler;
	act.sa_flags=SA_RESTART;
	act.sa_mask=0;
	if (sigaction (SIGCHLD,&act,NULL)==-1) return (-1);

	av=(char**)malloc (sizeof(char*)*2);
	av[0]=(char*)malloc (64);
	av[1]=NULL;

	// real unix test: strcpy (av[0],"/usr/bin/ls");
	strcpy (av[0],"/usr/bin/dir.exe");

#if defined (TEST_USE_FGETS)
	while (fgets(buf,64,stdin)!=NULL) {
#else
	while (1==1) {
#endif
		switch (revpid=fork()) {
		case -1:
			return (-1);
		case 0:
#if defined (TEST_USE_SETSID)
			setsid();
#endif
			execvp(av[0],av);
			_exit (0);
		default:
			break;
		}

		/* Wait for the process to die */
		errno=0;
		kill(revpid,0);
		while (errno!=ESRCH) {
			sleep(1);
			kill(revpid,0);
		}
	}
	return (0);
}

--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]