This is the mail archive of the
cygwin-patches
mailing list for the Cygwin project.
Re: Add wrappers for ExitProcess, TerminateProcess
Corinna Vinschen wrote:
> I can live with both variations, though I like the one entry point idea
> as in `cygwin_internal (CW_EXIT_PROCESS, UINT, bool)' more.
As re-implemented, attached. (I used the windows BOOL type, rather than
the C99/C++ bool type). Test case:
===================================
#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_RELOCATION,
TRUE);
// FALSE);
exit (1);
}
===================================
$ gcc -o foo.exe foo.c
$ ./foo.exe
$ echo $?
127
2009-10-05 Charles Wilson <...>
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.
* exceptions.cc: Move global variable sigExeced...
* globals.cc: here.
OK?
--
Chuck
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 6 Oct 2009 13:47:35 -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 6 Oct 2009 13:47:36 -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);
+ BOOL useTerminateProcess = va_arg (arg, BOOL);
+ exit_process (status, useTerminateProcess); /* 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 6 Oct 2009 13:47:36 -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 6 Oct 2009 13:47:36 -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 6 Oct 2009 13:47:36 -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 6 Oct 2009 13:47:36 -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 */