This is the mail archive of the cygwin 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]
Other format: [Raw text]

Re: fork failure?


Charles Wilson wrote:
> Dave Korn wrote:
>>   Umm, yes.  Poking around directly inside a sigjmp_buf.  Wonder if the layout
>> is actually what that code expects it to be or not?  That's where I'd start
>> looking next, anyway, if I was wondering why maybe things were randomly
>> jumping to unexpected places ...
> 
> Oh gosh. I hope that code isn't actually "live" in the cygwin
> build...yeah, messing around with jmp_bufs behind cygwin's -- or ANY
> OS's -- back is just bound to screw up.  Sigh.

Ok, it's pth's fault.  As it happens, none of the tests in pth's test
suite use fork(); that seems to be a serious oversight.  Anyway, here
are two dirt-simple apps. One using pthreads, the other using pth.
'Course, you need pth to build the latter.

gcc -o pth-fork pth-fork.c -lpth
gcc -o pthreads-fork pthreads-fork.c


$ ./pthreads-fork
FORKPARENT: mypid=7328 childpid=7724
FORKCHILD: mypid=7724

$ ./pth-fork
FORKPARENT: mypid=7140 childpid=7840

It looks like this is a long-standing problem:
http://www.cygwin.com/ml/cygwin/2001-05/threads.html#01131

Then, as now, suspicion falls on messing with jmp_buf and/or the stack
in bad ways.

(Note: using -DPTH_SYSCALL_SOFT=1 to force using pth_fork() as a wrapper
around the system fork() doesn't help. Same bad behavior.)

I wonder what's more difficult...fixing pth, or modifying libassuan and
gnupg to use plain old pthreads instead of pth?

Typically, there's a big performance impact between native threads
(slow, but pre-emptive) and user-mode threads (fast, but
non-pre-emptive).  However, on windows, I believe you don't have nearly
as much of a performance penalty using native threads (which cygwin's
pthread implementation uses under the hood).  So, modifying the code to
use pthreads wouldn't be bad, from a performance standpoint...but the
APIs are /just annoyingly different enough/ to be painful.

Hmmm...or writing shim wrappers to translate pth calls to pthread?

Ach, the purist in me just wants to get pth working...

I've attached the two test progs, and the cygport for pth. (sans source.
use 'cygport *.cygport get').

--
Chuck

Attachment: pth-2.0.7-1.cygport.tar.bz2
Description: Binary data

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <sys/errno.h>

void *test (void *arg);

int
main (int argc, char *argv[])
{
  int err;
  pthread_t thread;
  void *threadrv;

  if ((err = pthread_create (&thread, NULL, test, NULL)) != 0)
    {
      printf ("Error on pthread_create %d:%s\n", err, strerror (err));
      exit (1);
    }

  if ((err = pthread_join (thread, &threadrv)) != 0)
    {
      printf ("Error on pthread_join %d:%s\n", err, strerror (err));
      exit (1);
    }
  return 0;
}

void *
test (void *arg)
{
  int pid;

  pid = fork ();
  if (pid < 0)
    {
      printf ("FORKFAILED\n");
    }
  else if (pid == 0)
    {
      printf ("FORKCHILD: mypid=%d\n", getpid ());
    }
  else
    {
      printf ("FORKPARENT: mypid=%d childpid=%d\n", getpid (), pid);
    }
}

#include <stdlib.h>
#include <stdio.h>
#include <pth.h>
#include <string.h>
#include <sys/errno.h>

void *test (void *arg);

int
main (int argc, char *argv[])
{
  int err;
  pth_t thread;
  void *threadrv;

  if ((err = pth_init ()) != TRUE)
    {
      printf ("Error on pth_init: %d: %s\n", errno, strerror (errno));
      exit (1);
    }

  if ((thread = pth_spawn (PTH_ATTR_DEFAULT, test, NULL)) == (pid_t) NULL)
    {
      printf ("Error on pth_spawn: %d: %s\n", errno, strerror (errno));
      exit (1);
    }

  if ((err = pth_join (thread, &threadrv)) != TRUE)
    {
      printf ("Error on pthread_join %d: %s\n", errno, strerror (errno));
      exit (1);
    }
  return 0;
}

void *
test (void *arg)
{
  int pid;

  pid = fork ();
  if (pid < 0)
    {
      printf ("FORKFAILED\n");
    }
  else if (pid == 0)
    {
      printf ("FORKCHILD: mypid=%d\n", getpid ());
    }
  else
    {
      printf ("FORKPARENT: mypid=%d childpid=%d\n", getpid (), pid);
    }
}


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      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]