diff options
Diffstat (limited to 'winsup/cygwin/external.cc')
-rw-r--r-- | winsup/cygwin/external.cc | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index e20bebf56..38b8c71e2 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -32,6 +32,7 @@ details. */ #include <iptypes.h> child_info *get_cygwin_startup_info (); +static void exit_process (UINT, bool) __attribute__((noreturn)); static winpids pids; @@ -161,6 +162,37 @@ sync_winenv () free (envblock); } +/* + * Cygwin-specific wrapper for win32 ExitProcess and TerminateProcess. + * It ensures that the correct exit code, derived from the specified + * status value, will be made available to this process's parent (if + * that parent is also a cygwin process). If useTerminateProcess is + * true, then TerminateProcess(GetCurrentProcess(),...) will be used; + * otherwise, ExitProcess(...) is called. + * + * 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(), + * ANSI abort(), or POSIX _exit(), rather than this function -- because + * calling ExitProcess or TerminateProcess, even through this wrapper, + * skips much of the cygwin process cleanup code. + */ +static void +exit_process (UINT status, bool useTerminateProcess) +{ + 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); + if (useTerminateProcess) + TerminateProcess (GetCurrentProcess(), status); + /* avoid 'else' clause to silence warning */ + ExitProcess (status); +} + + extern "C" unsigned long cygwin_internal (cygwin_getinfo_types t, ...) { @@ -375,6 +407,12 @@ cygwin_internal (cygwin_getinfo_types t, ...) seterrno(file, line); } break; + case CW_EXIT_PROCESS: + { + UINT status = va_arg (arg, UINT); + int useTerminateProcess = va_arg (arg, int); + exit_process (status, !!useTerminateProcess); /* no return */ + } default: break; |