From e4bb2b924b61883aa2a300ea250eea6bbb51c3e1 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sat, 20 Sep 2003 19:53:38 +0000 Subject: * spawn.cc (pthread_cleanup): New struct. (do_cleanup): New function. (spawn_guts): Initialize struct for pthread_cleanup handling to ensure proper restoration of signals if/when thread is cancelled. Restore settings using pthread_cancel_pop. --- winsup/cygwin/ChangeLog | 8 ++++++++ winsup/cygwin/spawn.cc | 42 +++++++++++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 6bdf4f729db..f992778ccdd 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,11 @@ +2003-09-20 Christopher Faylor + + * spawn.cc (pthread_cleanup): New struct. + (do_cleanup): New function. + (spawn_guts): Initialize struct for pthread_cleanup handling to ensure + proper restoration of signals if/when thread is cancelled. Restore + settings using pthread_cancel_pop. + 2003-09-19 Christopher Faylor * thread.h (__reent_t::init_clib): Declare new function. diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index b9768e9f601..cf5b69896b9 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -323,6 +323,28 @@ av::unshift (const char *what, int conv) return 1; } +struct pthread_cleanup +{ + _sig_func_ptr oldint; + _sig_func_ptr oldquit; + sigset_t oldmask; + pthread_cleanup (): oldint (NULL), oldquit (NULL), oldmask (0) {} +}; + +static void +do_cleanup (void *args) +{ +# define cleanup ((pthread_cleanup *) args) + if (cleanup->oldint) + signal (SIGINT, cleanup->oldint); + if (cleanup->oldquit) + signal (SIGQUIT, cleanup->oldquit); + if (cleanup->oldmask) + sigprocmask (SIG_SETMASK, &(cleanup->oldmask), NULL); +# undef cleanup +} + + static int __stdcall spawn_guts (const char * prog_arg, const char *const *argv, const char *const envp[], int mode) @@ -689,17 +711,17 @@ spawn_guts (const char * prog_arg, const char *const *argv, /* FIXME: There is a small race here */ - sigset_t old_mask; - _sig_func_ptr oldint = (_sig_func_ptr) NULL; - _sig_func_ptr oldquit = (_sig_func_ptr) NULL; + DWORD res; + pthread_cleanup cleanup; + pthread_cleanup_push (do_cleanup, (void *) &cleanup); if (mode == _P_SYSTEM) { sigset_t child_block; - oldint = signal (SIGINT, SIG_IGN); - oldquit = signal (SIGQUIT, SIG_IGN); + cleanup.oldint = signal (SIGINT, SIG_IGN); + cleanup.oldquit = signal (SIGQUIT, SIG_IGN); sigemptyset (&child_block); sigaddset (&child_block, SIGCHLD); - (void) sigprocmask (SIG_BLOCK, &child_block, &old_mask); + (void) sigprocmask (SIG_BLOCK, &child_block, &cleanup.oldmask); } /* Restore impersonation. In case of _P_OVERLAY this isn't @@ -792,7 +814,6 @@ spawn_guts (const char * prog_arg, const char *const *argv, sigproc_printf ("spawned windows pid %d", pi.dwProcessId); - DWORD res; BOOL exited; res = 0; @@ -885,12 +906,6 @@ spawn_guts (const char * prog_arg, const char *const *argv, case _P_WAIT: case _P_SYSTEM: waitpid (cygpid, (int *) &res, 0); - if (mode == _P_SYSTEM) - { - signal (SIGINT, oldint); - signal (SIGQUIT, oldquit); - sigprocmask (SIG_SETMASK, &old_mask, NULL); - } break; case _P_DETACH: res = 0; /* Lose all memory of this child. */ @@ -904,6 +919,7 @@ spawn_guts (const char * prog_arg, const char *const *argv, break; } + pthread_cleanup_pop (1); return (int) res; } -- cgit v1.2.1