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:
> Which appears ok, as far as it goes. 'Course, something dies eventually
> because I never do get to gpg-agent's "exec()" of pinvoke, after that fork.

Well, bad news. In the kernel, the child gets right up to the return
statement in fork(), returning 0.  But it never reaches the line after
the call to fork() in the user code.

Help?



In libassuan (which provides fork-a-child and communication protocols
between parent and child for gpg-agent), I've done this:

=====
cygwin_internal(CW_CONSOLE_PRINTF, "***USER: [%s] about to fork
(pid=%d)\n", name, getpid());

  (*ctx)->pid = fork ();

cygwin_internal(CW_CONSOLE_PRINTF, "***USER: [%s] after fork (mypid=%d,
forkpid=%d)\n", name, getpid(), (*ctx)->pid);
=====

where CW_CONSOLE_PRINTF is a new call that allows access from user space
to the kernel mode console_print() [*] functionality -- I know this is
not something we'd really want in the kernel, but it helps me ensure
that my in-kernel and user-mode debug output go to the same place.

[*] actually, a new console_vprintf(), for obvious reasons

I'm stuck with this printf-style debugging because (a) strace causes the
process to hang, and (b) attaching with gdb follows only the parent. I
haven't tried the FORKDEBUG or CYGWIN_FORK_SLEEP yet...  The former
probably won't work, as I'm debugging a grandchild but don't want to
debug the child.

Now, inside fork.cc I have a ton of console_printf's. Most
interestingly, I have

===== in frok::child =====
...
console_printf("child: frok::child returning 0\n");
  return 0;
}
==========================

and in fork() itself, the following is very near the end of the function:

===== in fork() =====
  if (ischild || res > 0)
{
console_printf("(child?): everything is ok (ischild=%d)\n",ischild);
    /* everything is ok */;
}
  else
     ... error handling ...


  syscall_printf ("%d = fork()", res);
console_printf("returning from fork: ischild=%d, res=%d\n",ischild,res);
  return res;
}
==========================


Here's my output:

   ***USER: [/usr/bin/pinentry-gtk-2.exe] about to fork (pid=6664)
   about to setjmp using 0x7FF8F5DC
   returned from setjmp using 0x7FF8F5DC (parent)
   ...
   (child): about to call grouped.child(esp)
[this is stuff in frok::child():]
   child is running.  pid 1452, ppid 0, stack here 0x7FF8F534
   child: sync with parent returned
   child: hParent 0x228, load_dlls 0, fork_info->stacksize 0x00000000
   child: about to call set_cygwin_privileges
   child: about to call clear_procimptoken
   child: about to call cygheap->user.reimpersonate
   child: about to do some debugging stuff
   child: about fixup_shms_after_fork
   child: getting ready to finish up: load_dlls=0
   child:a returned from fixup_after_fork; syncing with parent
   child:a returned from sync_with_parent
[this is the parent, now that the chile has sync'ed:]
   (child?): everything is ok (ischild=0)
   returning from fork: ischild=0, res=1452
[child again:]
   child: returned from init_console_handle. calling ForceCloseHandle1
[this is the parent, back user code in libassuan:]
   ***USER: [/usr/bin/pinentry-gtk-2.exe] after fork
            (mypid=6664,forkpid=1452)
[child is still in kernel, in frok::child()]
   child: about to call pthread::atforkchild
P: ***USER: [/usr/bin/pinentry-gtk-2.exe] parent. child pid=1452
C: child: about to call fixup_timers_after_fork
P: ***USER: [/usr/bin/pinentry-gtk-2.exe] parent about to handshake

[parent will now attempt to send data over the pipe to the child. This]
[should block until child is ready?]

[child, still in frok::child()]
   child: about to call ld_preload
   child: about to call fixup_hooks_after_fork
   child: about to call _my_tls.fixup_hooks_after_fork
   child: waiting for sigthread...
   child: frok::child returning 0
[child returns from frok::child to fork()]
   (child): returned from grouped.child(esp) res=0
   (child?): everything is ok (ischild=1)

[so, child says everything is fine, and is about to return from fork()
[to caller]

   returning from fork: ischild=1, res=0
   ***USER: [/usr/bin/pinentry-gtk-2.exe] parent returning with 67125247
The End.

The statement after fork() is never reached in the child process, even
tho fork() SAYS it is returning with 0. I would have EXPECTED to see:
   ***USER: [/usr/bin/pinentry-gtk-2.exe] after fork
            (mypid=1452,forkpid=0)

Since the handshake fails, parent returns with an error code (67125247).

I note that procmon indicates that the child process exited with code
-1073741783, which in hex is 0xc0000029.  If that's an NTSTATUS value,
then it means STATUS_INVALID_UNWIND_TARGET, but that might be a red herring.

Any ideas?

--
Chuck

--
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]