summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog13
-rw-r--r--winsup/cygwin/spawn.cc55
2 files changed, 42 insertions, 26 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 60e0a301f..8a0b399ba 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,18 @@
2013-04-30 Christopher Faylor <me.cygwin2013@cgf.cx>
+ * 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.
+
+2013-04-30 Christopher Faylor <me.cygwin2013@cgf.cx>
+
* exceptions.cc (cygwin_exception::dumpstack): Guard against wild
pointer dereference.
(CYG_EXC_CONTINUE_EXECUTION): Define based on standard Windows
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;
}