Index: winsup/cygwin/exceptions.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/exceptions.cc,v retrieving revision 1.335 diff -u -p -r1.335 exceptions.cc --- winsup/cygwin/exceptions.cc 19 Sep 2009 15:34:19 -0000 1.335 +++ winsup/cygwin/exceptions.cc 5 Oct 2009 23:14:27 -0000 @@ -40,7 +40,6 @@ extern void sigdelayed (); }; extern child_info_spawn *chExeced; -int NO_COPY sigExeced; static BOOL WINAPI ctrl_c_handler (DWORD); static WCHAR windows_system_directory[1024]; Index: winsup/cygwin/external.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/external.cc,v retrieving revision 1.107 diff -u -p -r1.107 external.cc --- winsup/cygwin/external.cc 21 Sep 2009 02:19:31 -0000 1.107 +++ winsup/cygwin/external.cc 5 Oct 2009 23:14:27 -0000 @@ -32,6 +32,7 @@ details. */ #include child_info *get_cygwin_startup_info (); +static void exit_process (UINT) __attribute__ ((noreturn)); static winpids pids; @@ -161,6 +162,60 @@ sync_winenv () free (envblock); } +/* + * Cygwin-specific wrapper for win32 TerminateProcess. It ensures + * that if used to terminate the current process, then the correct + * exit code will be made available to this process's parent (if + * that parent is also a cygwin process). Otherwise, it simply + * delegates to the win32 TerminateProcess. Used by startup code + * for cygwin processes which is linked statically into + * applications, and is not part of the cygwin DLL -- which is why + * this interface is exposed. "Normal" programs should use ANSI + * abort() or POSIX _exit(), because calling TerminateProcess even + * through this wrapper, skips much of the cygwin process cleanup + * code. + */ +static BOOL +terminate_process (HANDLE process, UINT status) +{ + DWORD currPID = GetCurrentProcessId(); + if (GetProcessId(process) == currPID) + { + pid_t pid = getpid (); + external_pinfo * ep = fillout_pinfo (pid, 1); + DWORD dwpid = ep ? ep->dwProcessId : pid; + pinfo p (pid, PID_MAP_RW); + if ((dwpid == currPID) && (p->pid == ep->pid)) + p.set_exit_code ((DWORD)status); + } + return TerminateProcess (process, status); +} + +/* + * Cygwin-specific wrapper for win32 ExitProcess. It ensures that if + * used to terminate the current process, then the correct exit code + * will be made available to this process's parent (if that parent + * is also a cygwin process). Otherwise, it simply delegates to the + * win32 ExitProcess. Used by startup code for cygwin processes + * which is linked statically into applications, and is not part of + * the cygwin DLL -- which is why this interface is exposed. + * "Normal" programs should use ANSI exit(), because calling + * ExitProcess, even through this wrapper, skips much of the cygwin + * process cleanup code. + */ +static void +exit_process (UINT status) +{ + pid_t pid = getpid (); + external_pinfo * ep = fillout_pinfo (pid, 1); + DWORD dwpid = ep ? ep->dwProcessId : pid; + pinfo p (pid, PID_MAP_RW); + if ((dwpid == GetCurrentProcessId()) && (p->pid == ep->pid)) + p.set_exit_code ((DWORD)status); + ExitProcess (status); +} + + extern "C" unsigned long cygwin_internal (cygwin_getinfo_types t, ...) { @@ -375,6 +430,18 @@ cygwin_internal (cygwin_getinfo_types t, seterrno(file, line); } break; + case CW_TERMINATE_PROCESS: + { + HANDLE process = va_arg (arg, HANDLE); + UINT status = va_arg (arg, UINT); + terminate_process (process, status); + } + break; + case CW_EXIT_PROCESS: + { + UINT status = va_arg (arg, UINT); + exit_process (status); /* no return */ + } default: break; Index: winsup/cygwin/globals.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/globals.cc,v retrieving revision 1.9 diff -u -p -r1.9 globals.cc --- winsup/cygwin/globals.cc 24 Aug 2009 11:14:30 -0000 1.9 +++ winsup/cygwin/globals.cc 5 Oct 2009 23:14:27 -0000 @@ -49,6 +49,10 @@ SYSTEM_INFO system_info; /* Set in init.cc. Used to check if Cygwin DLL is dynamically loaded. */ int NO_COPY dynamically_loaded; +/* set in exceptions.cc. Used to store the desired exit value when + a process is killed by a signal */ +int NO_COPY sigExeced; + bool display_title; bool strip_title_path; bool allow_glob = true; Index: winsup/cygwin/pinfo.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/pinfo.cc,v retrieving revision 1.253 diff -u -p -r1.253 pinfo.cc --- winsup/cygwin/pinfo.cc 12 Jul 2009 21:15:47 -0000 1.253 +++ winsup/cygwin/pinfo.cc 5 Oct 2009 23:14:28 -0000 @@ -136,11 +136,18 @@ status_exit (DWORD x) # define self (*this) void +pinfo::set_exit_code (DWORD x) +{ + if (x >= 0xc0000000UL) + x = status_exit (x); + self->exitcode = EXITCODE_SET | (sigExeced ?: (x & 0xff) << 8); +} + +void pinfo::maybe_set_exit_code_from_windows () { DWORD x = 0xdeadbeef; DWORD oexitcode = self->exitcode; - extern int sigExeced; if (hProcess && !(self->exitcode & EXITCODE_SET)) { @@ -148,9 +155,7 @@ pinfo::maybe_set_exit_code_from_windows process hasn't quite exited after closing pipe */ GetExitCodeProcess (hProcess, &x); - if (x >= 0xc0000000UL) - x = status_exit (x); - self->exitcode = EXITCODE_SET | (sigExeced ?: (x & 0xff) << 8); + set_exit_code (x); } sigproc_printf ("pid %d, exit value - old %p, windows %p, cygwin %p", self->pid, oexitcode, x, self->exitcode); Index: winsup/cygwin/pinfo.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/pinfo.h,v retrieving revision 1.108 diff -u -p -r1.108 pinfo.h --- winsup/cygwin/pinfo.h 20 Dec 2008 17:32:31 -0000 1.108 +++ winsup/cygwin/pinfo.h 5 Oct 2009 23:14:28 -0000 @@ -155,6 +155,7 @@ public: } void exit (DWORD n) __attribute__ ((noreturn, regparm(2))); void maybe_set_exit_code_from_windows () __attribute__ ((regparm(1))); + void set_exit_code (DWORD n) __attribute__ ((regparm(2))); _pinfo *operator -> () const {return procinfo;} int operator == (pinfo *x) const {return x->procinfo == procinfo;} int operator == (pinfo &x) const {return x.procinfo == procinfo;} Index: winsup/cygwin/include/sys/cygwin.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/include/sys/cygwin.h,v retrieving revision 1.80 diff -u -p -r1.80 cygwin.h --- winsup/cygwin/include/sys/cygwin.h 7 Jul 2009 20:12:44 -0000 1.80 +++ winsup/cygwin/include/sys/cygwin.h 5 Oct 2009 23:14:28 -0000 @@ -142,7 +142,9 @@ typedef enum CW_CYGTLS_PADSIZE, CW_SET_DOS_FILE_WARNING, CW_SET_PRIV_KEY, - CW_SETERRNO + CW_SETERRNO, + CW_TERMINATE_PROCESS, + CW_EXIT_PROCESS } cygwin_getinfo_types; #define CW_NEXTPID 0x80000000 /* or with pid to get next one */