diff options
author | Christopher Faylor <me@cgf.cx> | 2013-05-01 03:51:08 +0400 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2013-05-01 03:51:08 +0400 |
commit | 3cb9da14617c58c2821c80d48f0bd80a2deb5fdf (patch) | |
tree | 33a5c8c366c63360a766696505b74d29a320d3bb /winsup/cygwin/spawn.cc | |
parent | cc5bdf003f650ce5938640c4dd1ffd84259dcc42 (diff) |
* spawn.cc (system_call_cleanup): Rename from pthread_cleanup. Extend
functionality.
(system_call_cleanup::system_call_cleanup): Set up signals like system()
requires. Unblock previously-blocked signal handling.
(system_call_cleanup::~system_call_cleanup): Restore signal handling after
system().
(child_info_spawn::worker): Put signals on hold and use system_call_cleanup
class to set and restore signals rather than doing it prior to to running the
program. Remove the ill-conceived pthread_cleanup stuff.
Diffstat (limited to 'winsup/cygwin/spawn.cc')
-rw-r--r-- | winsup/cygwin/spawn.cc | 55 |
1 files changed, 29 insertions, 26 deletions
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 1225a3765..5a748a42e 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -234,26 +234,37 @@ iscmd (const char *argv0, const char *what) (n == 0 || isdirsep (argv0[n - 1])); } -struct pthread_cleanup +struct system_call_cleanup { _sig_func_ptr oldint; _sig_func_ptr oldquit; sigset_t oldmask; - pthread_cleanup (): oldint (NULL), oldquit (NULL), oldmask ((sigset_t) -1) {} -}; - -static void -do_cleanup (void *args) -{ -# define cleanup ((pthread_cleanup *) args) - if (cleanup->oldmask != (sigset_t) -1) - { - signal (SIGINT, cleanup->oldint); - signal (SIGQUIT, cleanup->oldquit); - sigprocmask (SIG_SETMASK, &(cleanup->oldmask), NULL); - } + system_call_cleanup (bool issystem) + { + if (!issystem) + oldint = (_sig_func_ptr) -1; + else + { + sigset_t child_block; + oldint = signal (SIGINT, SIG_IGN); + oldquit = signal (SIGQUIT, SIG_IGN); + sigemptyset (&child_block); + sigaddset (&child_block, SIGCHLD); + sigprocmask (SIG_BLOCK, &child_block, &oldmask); + sig_send (NULL, __SIGNOHOLD); + } + } + ~system_call_cleanup () + { + if (oldmask != (sigset_t) -1) + { + signal (SIGINT, oldint); + signal (SIGQUIT, oldquit); + sigprocmask (SIG_SETMASK, &oldmask, NULL); + } + } # undef cleanup -} +}; child_info_spawn NO_COPY ch_spawn; @@ -295,17 +306,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, } /* FIXME: There is a small race here and FIXME: not thread safe! */ - pthread_cleanup cleanup; if (mode == _P_SYSTEM) - { - sigset_t child_block; - cleanup.oldint = signal (SIGINT, SIG_IGN); - cleanup.oldquit = signal (SIGQUIT, SIG_IGN); - sigemptyset (&child_block); - sigaddset (&child_block, SIGCHLD); - sigprocmask (SIG_BLOCK, &child_block, &cleanup.oldmask); - } - pthread_cleanup_push (do_cleanup, (void *) &cleanup); + sig_send (NULL, __SIGHOLD); av newargv; linebuf one_line; PWCHAR envblock = NULL; @@ -739,6 +741,8 @@ loop: goto out; } + system_call_cleanup (mode == _P_SYSTEM); + /* The CREATE_SUSPENDED case is handled below */ if (iscygwin () && !(c_flags & CREATE_SUSPENDED)) strace.write_childpid (pi.dwProcessId); @@ -880,7 +884,6 @@ out: this->cleanup (); if (envblock) free (envblock); - pthread_cleanup_pop (1); return (int) res; } |