* 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:
Christopher Faylor
2012-03-16 20:20:29 +00:00
parent d3f6480e44
commit 4aeaedf961
7 changed files with 192 additions and 169 deletions

View File

@ -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)