* fork.cc (lock_signals): Move to sigproc.h.
(lock_pthread): Ditto. (hold_everything): Ditto. (frok::parent): Call myself.prefork() just before calling CreateProcess. Call myself.postfork () on function exit. * pinfo.cc (pinfo::pending_rd_proc_pipe): Define. (pinfo::pending_wr_proc_pipe): Ditto. (_pinfo::dup_proc_pipe): Delete. (pinfo::wait): Move pipe creation into pinfo::prefork. Set pipe variables from pending_*. (_pinfo::sync_proc_pipe): Delete. (_pinfo::proc_pipe_owner): Ditto. (pinfo::prefork): Define new function. (pinfo::postfork): Ditto. (pinfo::postexec): Ditto. (_pinfo::alert_parent): Remove obsolete call to sync_proc_pipe. (_pinfo::dup_proc_pipe): Delete declaration. (_pinfo::sync_proc_pipe): Ditto. (pinfo::pending_rd_proc_pipe): Declare. (pinfo::pending_wr_proc_pipe): Ditto. (pinfo::prefork): Declare new function. (pinfo::postfork): Ditto. (pinfo::postexec): Ditto. (pinfo::wr_proc_pipe): Define new wrapper function. * sigproc.h: Include "sync.h". Move locking functions from fork to here. * spawn.cc (child_info_spawn::worker): Delete now-unneeded requirement to record orig_wr_proc_pipe. Call hold_everything prior to doing anything. Call myself.prefork() if spawning. Replace wr_proc_pipe synchronization with call to myself.postexec(). Call myself.postfork() if not execing. * sync.h: Replace #ifdef wrapper with "#pragma once".
This commit is contained in:
@ -11,6 +11,7 @@ details. */
|
||||
|
||||
#pragma once
|
||||
#include <signal.h>
|
||||
#include "sync.h"
|
||||
|
||||
#ifdef NSIG
|
||||
enum
|
||||
@ -121,4 +122,81 @@ extern char myself_nowait_dummy[];
|
||||
|
||||
extern struct sigaction *global_sigs;
|
||||
|
||||
class lock_signals
|
||||
{
|
||||
bool worked;
|
||||
public:
|
||||
lock_signals ()
|
||||
{
|
||||
worked = sig_send (NULL, __SIGHOLD) == 0;
|
||||
}
|
||||
operator int () const
|
||||
{
|
||||
return worked;
|
||||
}
|
||||
void dont_bother ()
|
||||
{
|
||||
worked = false;
|
||||
}
|
||||
~lock_signals ()
|
||||
{
|
||||
if (worked)
|
||||
sig_send (NULL, __SIGNOHOLD);
|
||||
}
|
||||
};
|
||||
|
||||
class lock_pthread
|
||||
{
|
||||
bool bother;
|
||||
public:
|
||||
lock_pthread (): bother (1)
|
||||
{
|
||||
pthread::atforkprepare ();
|
||||
}
|
||||
void dont_bother ()
|
||||
{
|
||||
bother = false;
|
||||
}
|
||||
~lock_pthread ()
|
||||
{
|
||||
if (bother)
|
||||
pthread::atforkparent ();
|
||||
}
|
||||
};
|
||||
|
||||
class hold_everything
|
||||
{
|
||||
public: /* DELETEME*/
|
||||
bool ischild;
|
||||
/* Note the order of the locks below. It is important,
|
||||
to avoid races, that the lock order be preserved.
|
||||
|
||||
pthread is first because it serves as a master lock
|
||||
against other forks being attempted while this one is active.
|
||||
|
||||
signals is next to stop signal processing for the duration
|
||||
of the fork.
|
||||
|
||||
process is last. If it is put before signals, then a deadlock
|
||||
could be introduced if the process attempts to exit due to a signal. */
|
||||
lock_pthread pthread;
|
||||
lock_signals signals;
|
||||
lock_process process;
|
||||
|
||||
public:
|
||||
hold_everything (bool x = false): ischild (x) {}
|
||||
operator int () const {return signals;}
|
||||
|
||||
~hold_everything()
|
||||
{
|
||||
if (ischild)
|
||||
{
|
||||
pthread.dont_bother ();
|
||||
process.dont_bother ();
|
||||
signals.dont_bother ();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#define myself_nowait ((_pinfo *) myself_nowait_dummy)
|
||||
|
Reference in New Issue
Block a user