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