Subject: Re: spawn hangs for non-Cygwin programs
From: Bob Wilson <[email-masked]>
To: [email-masked]
Date: Thu, 01 Mar 2001 15:36:42 -0800

This seems like a weakness in Cygwin.  Well, OK, so it's fine as long as
you don't try to get Cygwin apps to work nicely with native Win32 apps,
but still, it seems like a weakness.  There ought to be a way to spawn a
non-Cygwin executable with _P_NOWAIT.

Here is my attempt at a solution.  I simply added a _P_NONCYGWIN_CHILD
flag that can be ORed with _P_NOWAIT, and I modified spawn_guts() to
skip the synchronization when this flag is set.  I suspect that this new
flag will not work in combination with _P_OVERLAY, but I don't
understand that part of the code well enough to know how to test it.

Please let me know if you come up with a different solution.  I'd prefer
not to have to use a patched Cygwin DLL forever....

> On Wed, Feb 28, 2001 at 06:47:32PM -0500, Christopher Faylor wrote:
> >On Wed, Feb 28, 2001 at 01:24:10PM -0800, Bob Wilson wrote:
> >>I have a Cygwin program that contains the following call to invoke a
> >>child process:
> >>
> >>    pid = spawnvp((int)_P_NOWAIT, argv[0], argv);
> >>
> >>Sometime between Cygwin 1.1.4 and 1.1.8 it seems to have stopped
> >>working.  If the child is another Cygwin program, then everything is
> >>fine.  If the child was compiled with -mno-cygwin, however, the spawnvp
> >>call never returns (as if I hadn't specified _P_NOWAIT).
> >>
> >>Is this supposed to work?
> >
> >Yes.
> 
> Actually, on reflection, this is working as designed, unfortunately.  spawn
> relies on some synchronization with the cygwin process now and if the process
> is not a cygwin process, the synchronization never happens.  So, spawn
> waits for the program to terminate.

-- 
Bob Wilson                      Tel: (408) 327-7312
Tensilica, Inc.                 Fax: (408) 986-8919
3255-6 Scott Blvd.
Santa Clara, CA 95054

diff cygwin-1.1.8-2/winsup/cygwin/Changelog winsup/cygwin/Changelog
0a1,6
> Thu Mar  1 15:07:10 2001  Bob Wilson <[email-masked]>
> 
> 	* spawn.cc: Add _P_NONCYGWIN_CHILD flag to skip synchronization
> 	with the child. This is required to make _P_NOWAIT work when
> 	the child is not a Cygwin executable.
> 

diff cygwin-1.1.8-2/newlib/Changelog newlib/Changelog
0a1,7
> Thu Mar  1 15:07:10 2001  Bob Wilson <[email-masked]>
> 
> 	* libc/include/process.h: Add _P_NONCYGWIN_CHILD flag to skip
> 	synchronization with the child when compiling under Cygwin. This
> 	is required to make _P_NOWAIT work when the child is not a
> 	Cygwin executable.
> 

diff -u cygwin-1.1.8-2/winsup/cygwin/spawn.cc winsup/cygwin/spawn.cc
--- cygwin-1.1.8-2/winsup/cygwin/spawn.cc	Mon Jan 29 18:36:12 2001
+++ winsup/cygwin/spawn.cc	Thu Mar  1 14:14:15 2001
@@ -291,6 +291,10 @@
   BOOL rc;
   pid_t cygpid;
   sigframe thisframe (mainthread);
+  int nonCygwinChild;
+
+  nonCygwinChild = (mode & _P_NONCYGWIN_CHILD);
+  mode = (mode & _P_MODE_MASK);
 
   MALLOC_CHECK;
 
@@ -754,7 +758,12 @@
   res = 0;
   exited = FALSE;
   MALLOC_CHECK;
-  for (int i = 0; i < 100; i++)
+
+  /* If the child is not a Cygwin executable, skip the code to synchronize
+     with the child.  This probably doesn't work with _P_OVERLAY, but it is
+     essential for _P_NOWAIT because otherwise we'll get stuck waiting here
+     until the child exits. */
+  if (!nonCygwinChild) for (int i = 0; i < 100; i++)
     {
       switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE))
 	{
@@ -871,14 +880,14 @@
   int ret;
   vfork_save *vf = vfork_storage.val ();
 
-  if (vf != NULL && (vf->pid < 0) && mode == _P_OVERLAY)
-    mode = _P_NOWAIT;
+  if (vf != NULL && (vf->pid < 0) && (mode & _P_MODE_MASK) == _P_OVERLAY)
+    mode = (mode & ~_P_MODE_MASK) | _P_NOWAIT;
   else
     vf = NULL;
 
   syscall_printf ("_spawnve (%s, %s, %x)", path, argv[0], envp);
 
-  switch (mode)
+  switch (mode & _P_MODE_MASK)
     {
     case _P_OVERLAY:
       /* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/

diff -u cygwin-1.1.8-2/newlib/libc/include/process.h newlib/libc/include/process.h
--- cygwin-1.1.8-2/newlib/libc/include/process.h	Tue Jun  6 19:12:40 2000
+++ newlib/libc/include/process.h	Thu Mar  1 14:14:34 2001
@@ -51,6 +51,14 @@
 #define _P_NOWAITO	4
 #define _P_DETACH	5
 
+#ifdef __CYGWIN__
+/* Flag to specify that the child process is not a Cygwin executable so
+   that the spawn functions will not try to synchronize with the child.
+   This flag probably does not work in combination with _P_OVERLAY. */
+#define _P_NONCYGWIN_CHILD 0x80
+#define _P_MODE_MASK       0x7f
+#endif
+
 #define WAIT_CHILD 1
 
 #ifdef __cplusplus

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