gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r22623 - in gnunet: contrib src/include src/util


From: gnunet
Subject: [GNUnet-SVN] r22623 - in gnunet: contrib src/include src/util
Date: Thu, 12 Jul 2012 23:06:27 +0200

Author: LRN
Date: 2012-07-12 23:06:27 +0200 (Thu, 12 Jul 2012)
New Revision: 22623

Modified:
   gnunet/contrib/Makefile.am
   gnunet/contrib/gnunet_janitor.py.in
   gnunet/src/include/winproc.h
   gnunet/src/util/os_priority.c
   gnunet/src/util/win.cc
Log:
W32: safer process termination

Modified: gnunet/contrib/Makefile.am
===================================================================
--- gnunet/contrib/Makefile.am  2012-07-12 17:01:29 UTC (rev 22622)
+++ gnunet/contrib/Makefile.am  2012-07-12 21:06:27 UTC (rev 22623)
@@ -13,6 +13,7 @@
 endif
 
 noinst_SCRIPTS = \
+ terminate.py \
  gnunet_pyexpect.py \
  gnunet_janitor.py
 
@@ -28,6 +29,7 @@
  hostlist.cgi \
  hostlist.php \
  report.sh \
+ terminate.py.in \
  gnunet_pyexpect.py.in \
  gnunet_janitor.py.in \
  gnunet-gns-import.sh

Modified: gnunet/contrib/gnunet_janitor.py.in
===================================================================
--- gnunet/contrib/gnunet_janitor.py.in 2012-07-12 17:01:29 UTC (rev 22622)
+++ gnunet/contrib/gnunet_janitor.py.in 2012-07-12 21:06:27 UTC (rev 22623)
@@ -30,13 +30,11 @@
 import shutil
 import time
 import signal
+import terminate
 
 if os.name == 'nt':
   from win32com.client import GetObject
   WMI = GetObject('winmgmts:')
-  killsignal = signal.SIGTERM # any valid value will result in 
TerminateProcess()
-else:
-  killsignal = signal.SIGKILL  
 
 def get_process_list ():
   result = []
@@ -63,7 +61,7 @@
     if re.match (r'gnunet-service-arm', p[1]):
       print ("killing arm process {0:5} {1}".format (p[0], p[1]))
       try:
-        os.kill (int (p[0]), killsignal)
+        terminate.safe_terminate_process_by_pid (int (p[0]), 1)
       except OSError as e:
         print ("failed: {0}".format (e))
         pass
@@ -71,7 +69,7 @@
     if not re.match (r'gnunet-service-arm', p[1]):
       print ("killing non-arm process {0:5} {1}".format (p[0], p[1]))
       try:
-        os.kill (int (p[0]), killsignal)
+        terminate.safe_terminate_process_by_pid (int (p[0]), 1)
       except OSError as e:
         print ("failed: {0}".format (e))
         pass

Modified: gnunet/src/include/winproc.h
===================================================================
--- gnunet/src/include/winproc.h        2012-07-12 17:01:29 UTC (rev 22622)
+++ gnunet/src/include/winproc.h        2012-07-12 21:06:27 UTC (rev 22623)
@@ -227,6 +227,7 @@
   int GNInitWinEnv ();
   void GNShutdownWinEnv ();
 
+  BOOL SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout);
 #ifdef __cplusplus
 }
 #endif

Modified: gnunet/src/util/os_priority.c
===================================================================
--- gnunet/src/util/os_priority.c       2012-07-12 17:01:29 UTC (rev 22622)
+++ gnunet/src/util/os_priority.c       2012-07-12 21:06:27 UTC (rev 22623)
@@ -461,10 +461,16 @@
       if (0 != GetExitCodeProcess (proc->handle, &exitcode))
         must_kill = (exitcode == STILL_ACTIVE) ? GNUNET_YES : GNUNET_NO;
       if (GNUNET_YES == must_kill)
-        if (0 == TerminateProcess (proc->handle, 0))
+        if (0 == SafeTerminateProcess (proc->handle, 0, 0))
         {
-          SetErrnoFromWinError (GetLastError ());
-          return -1;
+          DWORD error_code = GetLastError ();
+          if (error_code != WAIT_TIMEOUT) /* OK, since timeout is 0 */
+          {
+            LOG (GNUNET_ERROR_TYPE_WARNING,
+                "SafeTermiateProcess failed with code %lu\n", error_code);
+            SetErrnoFromWinError (error_code);
+            return -1;
+          }
         }
     }
     return 0;
@@ -1386,7 +1392,7 @@
     /* If we can't pass on the socket(s), the child will block forever,
      * better put it out of its misery.
      */
-    TerminateProcess (gnunet_proc->handle, 0);
+    SafeTerminateProcess (gnunet_proc->handle, 0, 0);
     CloseHandle (gnunet_proc->handle);
     if (NULL != gnunet_proc->control_pipe)
       GNUNET_DISK_file_close (gnunet_proc->control_pipe);

Modified: gnunet/src/util/win.cc
===================================================================
--- gnunet/src/util/win.cc      2012-07-12 17:01:29 UTC (rev 22622)
+++ gnunet/src/util/win.cc      2012-07-12 21:06:27 UTC (rev 22623)
@@ -1261,6 +1261,75 @@
   return ret;
 }
 
+/**
+ * Terminate a process by creating a remote thread within it,
+ * which proceeds to call ExitProcess() inside that process.
+ * Safer than TerminateProcess ().
+ *
+ * Code is from From http://private-storm.de/2009/08/11/case-terminateprocess/
+ *
+ * @param hProcess handle of a process to terminate
+ * @param uExitCode exit code to use for ExitProcess()
+ * @param dwTimeout number of ms to wait for the process to terminate
+ * @return TRUE on success, FALSE on failure (check last error for the code)
+ */
+BOOL
+SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout)
+{
+  DWORD dwTID, dwCode, dwErr = 0;
+  HANDLE hProcessDup = INVALID_HANDLE_VALUE;
+  HANDLE hRT = NULL;
+  HINSTANCE hKernel = GetModuleHandle ("Kernel32");
+  BOOL bSuccess = FALSE;
+
+  BOOL bDup = DuplicateHandle (GetCurrentProcess (), hProcess,
+      GetCurrentProcess (), &hProcessDup, PROCESS_ALL_ACCESS,
+      FALSE, 0);
+
+  /* Detect the special case where the process is
+   * already dead...
+   */
+  if (GetExitCodeProcess (bDup ? hProcessDup : hProcess, &dwCode) &&
+      (STILL_ACTIVE ==  dwCode))
+  {
+    FARPROC pfnExitProc;
+
+    pfnExitProc = GetProcAddress (hKernel, "ExitProcess");
+
+    hRT = CreateRemoteThread ((bDup) ? hProcessDup : hProcess, NULL, 0,
+        (LPTHREAD_START_ROUTINE) pfnExitProc, (PVOID) uExitCode, 0, &dwTID);
+
+    dwErr = GetLastError ();
+  }
+  else
+  {
+    dwErr = ERROR_PROCESS_ABORTED;
+  }
+
+  if (hRT)
+  {
+    /* Must wait process to terminate to
+     * guarantee that it has exited...
+     */
+    DWORD dwWaitResult = WaitForSingleObject ((bDup) ? hProcessDup : hProcess,
+        dwTimeout);
+    if (dwWaitResult == WAIT_TIMEOUT)
+      dwErr = WAIT_TIMEOUT;
+    else
+      dwErr = GetLastError ();
+
+    CloseHandle (hRT);
+    bSuccess = dwErr == NO_ERROR;
+  }
+
+  if (bDup)
+    CloseHandle (hProcessDup);
+
+  SetLastError (dwErr);
+
+  return bSuccess;
+}
+
 } /* extern "C" */
 
 #endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]