From c529909f45fe73394d2846f6b886218449a4b2a0 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Tue, 20 Sep 2005 02:06:57 +0000 Subject: [PATCH] * dcrt0.cc (do_exit): Only call sigproc_terminate from one location -- pinfo::exit. * pinfo.cc (pinfo::exit): Move sigproc_terminate later so that signals can be processed while waiting for hExeced child. (pinfo::maybe_set_exit_code_from_windows): Set exit code from sigExeced if it is non-zero. Set exit_state to ES_EXEC_EXIT prior to waiting for captive process exit code. * exceptions.cc (sigExeced): New global variable. (signal_exit): Remove noreturn attribute from declaration. (signal_exit): Just terminate captive process and return if hExeced on the theory that the exit will be subsequently handled in the main thread. * sigproc.cc (sigproc_terminate): Eliminate test for ES_SIGPROCTERMINATE and use ES_FINAL instead. (sig_send): Use no_signals_available instead of duplicate test. * winsup.h (ES_EXEC_EXIT): New enum. (ES_SIGPROCTERMINATE): Delete. --- winsup/cygwin/ChangeLog | 20 ++++++++++++++++++++ winsup/cygwin/dcrt0.cc | 3 --- winsup/cygwin/exceptions.cc | 20 +++++++++++--------- winsup/cygwin/pinfo.cc | 15 ++++++++++----- winsup/cygwin/sigproc.cc | 6 +++--- winsup/cygwin/winsup.h | 2 +- 6 files changed, 45 insertions(+), 21 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 0f359da9a..f76e8ff7a 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,23 @@ +2005-09-19 Christopher Faylor + + * dcrt0.cc (do_exit): Only call sigproc_terminate from one location -- + pinfo::exit. + * pinfo.cc (pinfo::exit): Move sigproc_terminate later so that signals + can be processed while waiting for hExeced child. + (pinfo::maybe_set_exit_code_from_windows): Set exit code from sigExeced + if it is non-zero. Set exit_state to ES_EXEC_EXIT prior to waiting for + captive process exit code. + * exceptions.cc (sigExeced): New global variable. + (signal_exit): Remove noreturn attribute from declaration. + (signal_exit): Just terminate captive process and return if hExeced on + the theory that the exit will be subsequently handled in the main + thread. + * sigproc.cc (sigproc_terminate): Eliminate test for + ES_SIGPROCTERMINATE and use ES_FINAL instead. + (sig_send): Use no_signals_available instead of duplicate test. + * winsup.h (ES_EXEC_EXIT): New enum. + (ES_SIGPROCTERMINATE): Delete. + 2005-09-19 Christopher Faylor * sigproc.cc (talktome): Take siginfo_t argument. Don't scan all pids diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index f293901b8..39dd08c13 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -1091,9 +1091,6 @@ do_exit (int status) } - if (exit_state < ES_SIGPROCTERMINATE) - sigproc_terminate (ES_SIGPROCTERMINATE); // sets exit_state directly - if (exit_state < ES_TITLE) { exit_state = ES_TITLE; diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 0f61409ab..efd49ce6f 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -36,10 +36,11 @@ static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *); extern void sigdelayed (); }; -extern DWORD dwExeced; +extern NO_COPY DWORD dwExeced; +int NO_COPY sigExeced; static BOOL WINAPI ctrl_c_handler (DWORD); -static void signal_exit (int) __attribute__ ((noreturn)); +static void signal_exit (int); char windows_system_directory[1024]; static size_t windows_system_directory_length; @@ -1160,7 +1161,7 @@ exit_sig: } sigproc_printf ("signal %d, about to call do_exit", si.si_signo); signal_exit (si.si_signo); - /* Never returns */ + /* May not return */ } CRITICAL_SECTION NO_COPY exit_lock; @@ -1171,6 +1172,13 @@ CRITICAL_SECTION NO_COPY exit_lock; static void signal_exit (int rc) { + if (hExeced) + { + sigproc_printf ("terminating captive process"); + TerminateProcess (hExeced, sigExeced = rc); + return; + } + EnterCriticalSection (&exit_lock); if (exit_already++) myself.exit (rc); @@ -1184,12 +1192,6 @@ signal_exit (int rc) user_data->resourcelocks->Delete (); user_data->resourcelocks->Init (); - if (hExeced) - { - sigproc_printf ("terminating captive process"); - TerminateProcess (hExeced, rc); - } - sigproc_printf ("about to call do_exit (%x)", rc); SetEvent (signal_arrived); do_exit (rc); diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 5d0b890b0..f28d7155f 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -111,13 +111,15 @@ pinfo::maybe_set_exit_code_from_windows () { DWORD x = 0xdeadbeef; DWORD oexitcode = self->exitcode; + extern int sigExeced; + if (hProcess && !(self->exitcode & EXITCODE_SET)) { WaitForSingleObject (hProcess, INFINITE); // just to be safe, in case // process hasn't quite exited // after closing pipe GetExitCodeProcess (hProcess, &x); - self->exitcode = EXITCODE_SET | (x & 0xff) << 8; + self->exitcode = EXITCODE_SET | (sigExeced ?: (x & 0xff) << 8); } sigproc_printf ("pid %d, exit value - old %p, windows %p, cygwin %p", self->pid, oexitcode, x, self->exitcode); @@ -136,11 +138,16 @@ pinfo::zap_cwd () void pinfo::exit (DWORD n) { - sigproc_terminate (ES_FINAL); - cygthread::terminate (); if (n != EXITCODE_NOSET) self->exitcode = EXITCODE_SET | n;/* We're really exiting. Record the UNIX exit code. */ + else + { + exit_state = ES_EXEC_EXIT; + maybe_set_exit_code_from_windows (); + } + + sigproc_terminate (ES_FINAL); /* FIXME: There is a potential race between an execed process and its parent here. I hated to add a mutex just for this, though. */ @@ -148,8 +155,6 @@ pinfo::exit (DWORD n) fill_rusage (&r, hMainProc); add_rusage (&self->rusage_self, &r); - maybe_set_exit_code_from_windows (); - if (n != EXITCODE_NOSET) { zap_cwd (); diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 59f79961d..b9c66f376 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -492,7 +492,7 @@ sigproc_terminate (exit_states es) { exit_states prior_exit_state = exit_state; exit_state = es; - if (prior_exit_state > ES_SIGPROCTERMINATE) + if (prior_exit_state >= ES_FINAL) sigproc_printf ("already performed"); else { @@ -541,7 +541,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) } else { - if (!my_sendsig || (si.si_signo != __SIGEXIT && myself->exitcode & EXITCODE_SET) || &_my_tls == _sig_tls) + if (no_signals_available (si.si_signo != __SIGEXIT)) { sigproc_printf ("my_sendsig %p, myself->sendsig %p, exit_state %d", my_sendsig, myself->sendsig, exit_state); @@ -638,7 +638,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) } else { - if (no_signals_available (si.si_signo != __SIGEXIT)) + if (no_signals_available (true)) sigproc_printf ("I'm going away now"); else if (!p->exec_sendsig) system_printf ("error sending signal %d to pid %d, pipe handle %p, %E", diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 960c6c4fa..d31dd9abd 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -195,7 +195,7 @@ enum exit_states ES_CLOSEALL, ES_HUP_PGRP, ES_HUP_SID, - ES_SIGPROCTERMINATE, + ES_EXEC_EXIT, ES_TITLE, ES_TTY_TERMINATE, ES_FINAL