Christopher Faylor wrote: > On Tue, Oct 06, 2009 at 05:19:03PM -0400, Charles Wilson wrote: >> Do I need to increment the minor version when adding a new >> cygwin_internal call? It seems so: > > Yes. Thanks for catching that.
As committed (and tested): 2009-10-05 Charles Wilson <cyg...@cwilson.fastmail.fm> Add cygwin wrapper for ExitProcess and TerminateProcess. * include/sys/cygwin.h: Declare new cygwin_getinfo_type CW_EXIT_PROCESS. * external.cc (exit_process): New function. (cygwin_internal): Handle CW_EXIT_PROCESS. * pinfo.h (pinfo::set_exit_code): New method. * pinfo.cc (pinfo::set_exit_code): New, refactored from... (pinfo::maybe_set_exit_code_from_windows): here. Call it. * include/cygwin/version.h: Bump CYGWIN_VERSION_API_MINOR to 215 to reflect the above change. Test proggie: ======================================================== #include <stdio.h> #include <windows.h> #include <ntdef.h> #include <sys/cygwin.h> #define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xc0000269) #define STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION ((NTSTATUS) 0xe0000269) #define STATUS_DLL_NOT_FOUND ((NTSTATUS) 0xc0000135) int main(int argc, char* argv[]) { cygwin_internal (CW_EXIT_PROCESS, STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION, 1); // 0); exit (1); } ======================================================== Note that neither cygwin nor ExitProcess/TerminateProcess care that they have no idea what the '0xe0000269' status code means -- for this test I stripped out all of the new pseudo-reloc support code from my repo. However, cygwin just says: "this value is > 0xc00000000, and I don't have a special case to handle it, so default: exit_code = 127;" Which is what we want, for now. $ gcc -o foo.exe foo.c $ ./foo.exe $ echo $? 127 P.S. Thanks for all the reviews, folks! Public interface changes should always be subject to "strict scrutiny", even more so than purely internal implementation details, so this was good... -- Chuck
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 6 Oct 2009 21:50:41 -0000 @@ -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; Index: winsup/cygwin/pinfo.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/pinfo.cc,v retrieving revision 1.254 diff -u -p -r1.254 pinfo.cc --- winsup/cygwin/pinfo.cc 6 Oct 2009 03:39:38 -0000 1.254 +++ winsup/cygwin/pinfo.cc 6 Oct 2009 21:50:41 -0000 @@ -136,6 +136,14 @@ 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; @@ -147,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 6 Oct 2009 21:50:41 -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/cygwin/version.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/include/cygwin/version.h,v retrieving revision 1.299 diff -u -p -r1.299 version.h --- winsup/cygwin/include/cygwin/version.h 26 Sep 2009 21:01:10 -0000 1.299 +++ winsup/cygwin/include/cygwin/version.h 6 Oct 2009 21:50:42 -0000 @@ -368,12 +368,13 @@ details. */ 212: Add and export libstdc++ malloc wrappers. 213: Export canonicalize_file_name, eaccess, euidaccess. 214: Export execvpe, fexecve. + 215: CW_EXIT_PROCESS added. */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 214 +#define CYGWIN_VERSION_API_MINOR 215 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible 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 6 Oct 2009 21:50:42 -0000 @@ -142,7 +142,8 @@ typedef enum CW_CYGTLS_PADSIZE, CW_SET_DOS_FILE_WARNING, CW_SET_PRIV_KEY, - CW_SETERRNO + CW_SETERRNO, + CW_EXIT_PROCESS } cygwin_getinfo_types; #define CW_NEXTPID 0x80000000 /* or with pid to get next one */