* dcrt0.cc (dll_crt0_1): Create vfork main storage here so that it can be

queried in waitsig later.
* sigproc.cc (wait_sig): Don't deliver a signal if in a vfork.
* fork.cc (vfork): Deliver all signals on parent return from vfork.
This commit is contained in:
Christopher Faylor 2001-09-15 00:47:44 +00:00
parent bf0338856a
commit 9661a0c8b7
7 changed files with 46 additions and 19 deletions

View File

@ -1,3 +1,10 @@
Fri Sep 14 20:43:01 2001 Christopher Faylor <cgf@cygnus.com>
* dcrt0.cc (dll_crt0_1): Create vfork main storage here so that it can
be queried in waitsig later.
* sigproc.cc (wait_sig): Don't deliver a signal if in a vfork.
* fork.cc (vfork): Deliver all signals on parent return from vfork.
Fri Sep 14 10:21:00 2001 Corinna Vinschen <corinna@vinschen.de>
* dcrt0.cc (_dll_crt0()): Don't call wincap.init() here.

View File

@ -534,6 +534,7 @@ alloc_stack (child_info_fork *ci)
static NO_COPY int mypid = 0;
int _declspec(dllexport) __argc;
char _declspec(dllexport) **__argv;
vfork_save NO_COPY *main_vfork = NULL;
void
sigthread::init (const char *s)
@ -644,6 +645,7 @@ dll_crt0_1 ()
events_init ();
cygheap->cwd.init ();
main_vfork = vfork_storage.create ();
cygbench ("pre-forkee");
if (user_data->forkee)

View File

@ -700,6 +700,7 @@ vfork ()
#ifndef NEWVFORK
return fork ();
#else
sigframe thisframe;
vfork_save *vf = get_vfork_val ();
char **esp, **pp;
@ -714,22 +715,22 @@ vfork ()
__asm__ volatile ("movl %%esp,%0": "=r" (vf->vfork_esp):);
__asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);
for (pp = (char **)vf->frame, esp = vf->vfork_esp;
esp <= vf->vfork_ebp + 1; pp++, esp++)
esp <= vf->vfork_ebp + 2; pp++, esp++)
*pp = *esp;
int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;
debug_printf ("%d = vfork()", res);
return res;
}
cygheap->fdtab.vfork_parent_restore ();
vf = get_vfork_val ();
__asm__ volatile ("movl %%esp,%0": "=r" (esp):);
for (pp = (char **)vf->frame, esp = vf->vfork_esp;
esp <= vf->vfork_ebp + 1; pp++, esp++)
esp <= vf->vfork_ebp + 2; pp++, esp++)
*esp = *pp;
thisframe.init (mainthread);
cygheap->fdtab.vfork_parent_restore ();
if (vf->pid < 0)
{
int exitval = -vf->pid;
@ -740,6 +741,7 @@ vfork ()
int pid = vf->pid;
vf->pid = 0;
sig_dispatch_pending ();
return pid;
#endif
}

View File

@ -67,10 +67,10 @@ but not yet dispatched in the main thread. If the sigsave structure
seems to be "active", then a "pending" flag is set (see below) and the
function returns. Otherwise processing continues.
After determining that sigsave is available, setup_handler will take
one of two routes, depending on whether the main thread is executing
in the cygwin DLL or is currently in "user" code. We'll discuss the
cygwin DLL case first.
After determining that sigsave is available, setup_handler will take one
of two routes, depending on whether the main thread is executing in the
cygwin DLL or is currently in "user" code. We'll discuss the cygwin DLL
case first.
If sigsave seems to be available, then the frame information for the
main thread is inspected. This information is set by any cygwin
@ -81,21 +81,33 @@ process. Any function which uses 'sigframe thisframe' should be signal
aware. It should detect when a signal has arrived and return
immediately.
So, if mainframe is active, that means that we have good information about
the state of the main thread. Cygwin uses the stack frame info from this
structure to insert a call to the assembly language function 'sigdelayed'
in place of the main thread's normal return address. So, when a call to
(e.g.) _read returns after detecting a signal, it does not return to its
caller. Rather, it returns to sigdelayed.
So, if mainframe is active, that means that we have good information
about the state of the main thread. Cygwin uses the stack frame info
from this structure to insert a call to the assembly language function
'sigdelayed' in place of the main thread's normal return address. So,
when a call to (e.g.) _read returns after detecting a signal, it does
not return to its caller. Rather, it returns to sigdelayed.
The sigdelayed function saves a lot of state on the stack and sets the
signal mask as appropriate for POSIX. It uses information from the
sigsave structure which has been filled in by interrupt_on_return, as
called by setup_handler. sigdelayed pushes a "call" the function
called by setup_handler. sigdelayed pushes a "call" to the function
"sigreturn" on the stack. This will be the return address seen by the
signal handler. After setting up the return value, modifying the signal
mask, and saving other information on the stack, sigreturn clears the
sigsave structure (so that setup_handler can use it) and jumps to the
signal handler function.
signal handler function. And, so a UNIX signal handler function is
emulated.
The signal handler function operates as normal for UNIX but, upon
return, it does not go directly back to the return address of the
original cygwin function. Instead it returns to the previously
mentioned 'sigreturn' assembly language function.
sigreturn resets the process mask to its state prior to calling the
signal handler. It checks to see if any new signals have come in and
calls the handler for them now, ensuring that the order of signal
arrival is more or less maintained. It checks to see if a cygwin
routine has set a special "restore this errno on returning from a
signal" value and sets errno to this, if so. Finally, it restores all
of the register values that were in effect when sigdelayed was called.

View File

@ -68,7 +68,7 @@ public:
size_t size () {return sizeof (waitq);}
};
#ifdef NEED_VFORK
#if defined (NEED_VFORK)
struct vfork_save
{
int pid;
@ -87,6 +87,7 @@ public:
size_t size () {return sizeof (vfork_save);}
};
extern per_thread_vfork vfork_storage;
extern vfork_save *main_vfork;
#endif
extern "C" {

View File

@ -26,6 +26,7 @@ details. */
#include "dtable.h"
#include "cygheap.h"
#include "child_info.h"
#define NEED_VFORK
#include "perthread.h"
#include <assert.h>
#include "shared_info.h"
@ -1161,6 +1162,7 @@ wait_sig (VOID *)
if (sig > 0 && sig != SIGKILL && sig != SIGSTOP &&
(sigismember (&myself->getsigmask (), sig) ||
main_vfork->pid ||
(sig != SIGCONT && ISSTATE (myself, PID_STOPPED))))
{
sigproc_printf ("signal %d blocked", sig);

View File

@ -75,7 +75,8 @@ public:
}
sigframe (): st (NULL) {}
sigframe (sigthread &t, DWORD ebp = (DWORD) __builtin_frame_address (0))
sigframe (sigthread &t, DWORD ebp = (DWORD) __builtin_frame_address (0)) {init (t, ebp);}
void init (sigthread &t, DWORD ebp = (DWORD) __builtin_frame_address (0))
{
if (!t.frame && t.id == GetCurrentThreadId ())
set (t, ebp);