* 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:
parent
bf0338856a
commit
9661a0c8b7
|
@ -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>
|
Fri Sep 14 10:21:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* dcrt0.cc (_dll_crt0()): Don't call wincap.init() here.
|
* dcrt0.cc (_dll_crt0()): Don't call wincap.init() here.
|
||||||
|
|
|
@ -534,6 +534,7 @@ alloc_stack (child_info_fork *ci)
|
||||||
static NO_COPY int mypid = 0;
|
static NO_COPY int mypid = 0;
|
||||||
int _declspec(dllexport) __argc;
|
int _declspec(dllexport) __argc;
|
||||||
char _declspec(dllexport) **__argv;
|
char _declspec(dllexport) **__argv;
|
||||||
|
vfork_save NO_COPY *main_vfork = NULL;
|
||||||
|
|
||||||
void
|
void
|
||||||
sigthread::init (const char *s)
|
sigthread::init (const char *s)
|
||||||
|
@ -644,6 +645,7 @@ dll_crt0_1 ()
|
||||||
events_init ();
|
events_init ();
|
||||||
|
|
||||||
cygheap->cwd.init ();
|
cygheap->cwd.init ();
|
||||||
|
main_vfork = vfork_storage.create ();
|
||||||
|
|
||||||
cygbench ("pre-forkee");
|
cygbench ("pre-forkee");
|
||||||
if (user_data->forkee)
|
if (user_data->forkee)
|
||||||
|
|
|
@ -700,6 +700,7 @@ vfork ()
|
||||||
#ifndef NEWVFORK
|
#ifndef NEWVFORK
|
||||||
return fork ();
|
return fork ();
|
||||||
#else
|
#else
|
||||||
|
sigframe thisframe;
|
||||||
vfork_save *vf = get_vfork_val ();
|
vfork_save *vf = get_vfork_val ();
|
||||||
char **esp, **pp;
|
char **esp, **pp;
|
||||||
|
|
||||||
|
@ -714,22 +715,22 @@ vfork ()
|
||||||
__asm__ volatile ("movl %%esp,%0": "=r" (vf->vfork_esp):);
|
__asm__ volatile ("movl %%esp,%0": "=r" (vf->vfork_esp):);
|
||||||
__asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);
|
__asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);
|
||||||
for (pp = (char **)vf->frame, esp = vf->vfork_esp;
|
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;
|
*pp = *esp;
|
||||||
int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;
|
int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;
|
||||||
debug_printf ("%d = vfork()", res);
|
debug_printf ("%d = vfork()", res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
cygheap->fdtab.vfork_parent_restore ();
|
|
||||||
|
|
||||||
vf = get_vfork_val ();
|
vf = get_vfork_val ();
|
||||||
|
|
||||||
__asm__ volatile ("movl %%esp,%0": "=r" (esp):);
|
|
||||||
for (pp = (char **)vf->frame, esp = vf->vfork_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;
|
*esp = *pp;
|
||||||
|
|
||||||
|
thisframe.init (mainthread);
|
||||||
|
cygheap->fdtab.vfork_parent_restore ();
|
||||||
|
|
||||||
if (vf->pid < 0)
|
if (vf->pid < 0)
|
||||||
{
|
{
|
||||||
int exitval = -vf->pid;
|
int exitval = -vf->pid;
|
||||||
|
@ -740,6 +741,7 @@ vfork ()
|
||||||
|
|
||||||
int pid = vf->pid;
|
int pid = vf->pid;
|
||||||
vf->pid = 0;
|
vf->pid = 0;
|
||||||
|
sig_dispatch_pending ();
|
||||||
return pid;
|
return pid;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
seems to be "active", then a "pending" flag is set (see below) and the
|
||||||
function returns. Otherwise processing continues.
|
function returns. Otherwise processing continues.
|
||||||
|
|
||||||
After determining that sigsave is available, setup_handler will take
|
After determining that sigsave is available, setup_handler will take one
|
||||||
one of two routes, depending on whether the main thread is executing
|
of two routes, depending on whether the main thread is executing in the
|
||||||
in the cygwin DLL or is currently in "user" code. We'll discuss the
|
cygwin DLL or is currently in "user" code. We'll discuss the cygwin DLL
|
||||||
cygwin DLL case first.
|
case first.
|
||||||
|
|
||||||
If sigsave seems to be available, then the frame information for the
|
If sigsave seems to be available, then the frame information for the
|
||||||
main thread is inspected. This information is set by any cygwin
|
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
|
aware. It should detect when a signal has arrived and return
|
||||||
immediately.
|
immediately.
|
||||||
|
|
||||||
So, if mainframe is active, that means that we have good information about
|
So, if mainframe is active, that means that we have good information
|
||||||
the state of the main thread. Cygwin uses the stack frame info from this
|
about the state of the main thread. Cygwin uses the stack frame info
|
||||||
structure to insert a call to the assembly language function 'sigdelayed'
|
from this structure to insert a call to the assembly language function
|
||||||
in place of the main thread's normal return address. So, when a call to
|
'sigdelayed' in place of the main thread's normal return address. So,
|
||||||
(e.g.) _read returns after detecting a signal, it does not return to its
|
when a call to (e.g.) _read returns after detecting a signal, it does
|
||||||
caller. Rather, it returns to sigdelayed.
|
not return to its caller. Rather, it returns to sigdelayed.
|
||||||
|
|
||||||
The sigdelayed function saves a lot of state on the stack and sets the
|
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
|
signal mask as appropriate for POSIX. It uses information from the
|
||||||
sigsave structure which has been filled in by interrupt_on_return, as
|
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
|
"sigreturn" on the stack. This will be the return address seen by the
|
||||||
signal handler. After setting up the return value, modifying the signal
|
signal handler. After setting up the return value, modifying the signal
|
||||||
mask, and saving other information on the stack, sigreturn clears the
|
mask, and saving other information on the stack, sigreturn clears the
|
||||||
sigsave structure (so that setup_handler can use it) and jumps to 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.
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
size_t size () {return sizeof (waitq);}
|
size_t size () {return sizeof (waitq);}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef NEED_VFORK
|
#if defined (NEED_VFORK)
|
||||||
struct vfork_save
|
struct vfork_save
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
|
@ -87,6 +87,7 @@ public:
|
||||||
size_t size () {return sizeof (vfork_save);}
|
size_t size () {return sizeof (vfork_save);}
|
||||||
};
|
};
|
||||||
extern per_thread_vfork vfork_storage;
|
extern per_thread_vfork vfork_storage;
|
||||||
|
extern vfork_save *main_vfork;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -26,6 +26,7 @@ details. */
|
||||||
#include "dtable.h"
|
#include "dtable.h"
|
||||||
#include "cygheap.h"
|
#include "cygheap.h"
|
||||||
#include "child_info.h"
|
#include "child_info.h"
|
||||||
|
#define NEED_VFORK
|
||||||
#include "perthread.h"
|
#include "perthread.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "shared_info.h"
|
#include "shared_info.h"
|
||||||
|
@ -1161,6 +1162,7 @@ wait_sig (VOID *)
|
||||||
|
|
||||||
if (sig > 0 && sig != SIGKILL && sig != SIGSTOP &&
|
if (sig > 0 && sig != SIGKILL && sig != SIGSTOP &&
|
||||||
(sigismember (&myself->getsigmask (), sig) ||
|
(sigismember (&myself->getsigmask (), sig) ||
|
||||||
|
main_vfork->pid ||
|
||||||
(sig != SIGCONT && ISSTATE (myself, PID_STOPPED))))
|
(sig != SIGCONT && ISSTATE (myself, PID_STOPPED))))
|
||||||
{
|
{
|
||||||
sigproc_printf ("signal %d blocked", sig);
|
sigproc_printf ("signal %d blocked", sig);
|
||||||
|
|
|
@ -75,7 +75,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
sigframe (): st (NULL) {}
|
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 ())
|
if (!t.frame && t.id == GetCurrentThreadId ())
|
||||||
set (t, ebp);
|
set (t, ebp);
|
||||||
|
|
Loading…
Reference in New Issue