This is the mail archive of the cygwin-patches mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Add wrappers for ExitProcess, TerminateProcess


Christopher Faylor wrote:
> I've checked in the sigExeced part of this patch.  Thanks.

The checkin does not yet appear to have taken effect, because
  $ cvs update && cvs diff
still shows the sigExeced stuff -- so, it's still in the patch/changelog
below.

> For the other part, if you're willing, I think you should just do what
> Corinna suggested.

Attached. The implementation of terminate_process and exit_process may
be somewhat paranoid, but I really don't want to let anybody
accidentally kill the wrong process, or clobber their own exit value
when terminating some other process.


Tested with:
==============================================
#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_TERMINATE_PROCESS,
                   GetCurrentProcess(),
                   STATUS_ILLEGAL_DLL_RELOCATION);
//  cygwin_internal (CW_EXIT_PROCESS, STATUS_ILLEGAL_DLL_RELOCATION);
  exit (1);
}
==============================================


2009-10-05  Charles Wilson  <...>

	Add cygwin wrappers for ExitProcess and TerminateProcess.
	* include/sys/cygwin.h: Declare new cygwin_getinfo_types
	CW_TERMINATE_PROCESS and CW_EXIT_PROCESS.
	* external.cc (terminate_process): New function.
	(exit_process): New function.
	(cygwin_internal): Handle CW_TERMINATE_PROCESS and
	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.

--
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	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 <iptypes.h>
 
 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 */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]