Synchronization problem with posix_spawn

Ken Brown kbrown@cornell.edu
Thu Jul 30 23:04:30 GMT 2020


Hi Corinna,

On 7/30/2020 1:17 PM, Corinna Vinschen wrote:
> Hi Ken,
> 
> On Jul 30 13:59, Corinna Vinschen wrote:
>> On Jul 29 19:12, Ken Brown via Cygwin wrote:
>>> On 7/29/2020 4:17 PM, Ken Brown via Cygwin wrote:
>>>> posix_spawn(p) returns before the spawned process is fully up and
>>>> running.  [...]
>>> I just took a look at the source, and I see that posix_spawn was taken from
>>> FreeBSD.  Does FreeBSD have the same problem?  Should applications just be
>>> aware of this issue and insert a sleep after posix_spawn before sending
>>> signals?
>>
>> Actually, this is a Cygwin problem.  I just had a look into the
>> newlib implementation myself, and it turns out that the code,
>> in particular the do_posix_spawn() function, is BSD specific.  It
>> relies on the BSD implementation of vfork(2).  Cygwin's vfork(2)
>> on the other hand, is NOT following the historic idea of the
>> BSD vfork(2), rather it's equivalent to fork(2).  This is
>> POSIX compliant, but certainly the reliance of the BSD vfork
>> behaviour makes do_posix_spawn() as it's implemented right now,
>> not overly functional for Cygwin.
>>
>> IOW, we need a Cygwin-specific do_posix_spawn() using fork(2)
>> in conjunction with some synchronization the BSD function
>> gets "for free" by using its specific vfork(2).
> 
> Below is a POC implementation for a Cygwin-specific do_posix_spawn().
> If this does the trick (at least your testcase works in my testing),
> then I'm planning to move the function over to the winsup/cygwin dir
> so it can be streamlined further.
> 
> Can you give it a try?

It looks like something further is needed: 'wait' doesn't seem to recognize the 
spawned process.

I'm attaching a second test case.  This spawns a "sleep 10" process and then 
waits for termination.  If I run it on Cygwin, it returns immediately like this:

   $ ./spawn_test2
   wait: No child processes
   sleep 10 exited normally with status 0

and the sleep process is still running.  If I run it on Linux, I see

   $ ./spawn_test2
   sleep 10 exited normally with status 0

if I let the sleep process run to completion, or

   $ ./spawn_test2
   sleep 10 exited due to signal 15

if I run 'pkill sleep' in another terminal.

Ken
-------------- next part --------------
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <spawn.h>
#include <signal.h>
#include <sys/wait.h>

extern char **environ;

pid_t
run_sleep ()
{
  pid_t pid;
  char *argv[] = { "sleep", "10", NULL };
  int err = posix_spawnp (&pid, "/bin/sleep", NULL, NULL, argv, environ);
  if (err == 0)
    return pid;
  else
    {
      printf ("posix_spawnp: %s\n", strerror (err));
      exit (1);
    }
}

int
main ()
{
  int status;
  pid_t pid = run_sleep ();
  if (wait (&status) < 0)
    perror ("wait");
  if (WIFEXITED (status))
    printf ("sleep 10 exited normally with status %d\n", WEXITSTATUS (status));
  else if (WIFSIGNALED (status))
    printf ("sleep 10 exited due to signal %d\n", WTERMSIG (status));
  else
    printf ("????\n");
}


More information about the Cygwin mailing list