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 = []
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
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
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;
/* 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);
return ret;\r
}\r
\r
+/**
+ * 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\r
+SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout)\r
+{\r
+ DWORD dwTID, dwCode, dwErr = 0;\r
+ HANDLE hProcessDup = INVALID_HANDLE_VALUE;\r
+ HANDLE hRT = NULL;\r
+ HINSTANCE hKernel = GetModuleHandle ("Kernel32");\r
+ BOOL bSuccess = FALSE;\r
+\r
+ BOOL bDup = DuplicateHandle (GetCurrentProcess (), hProcess,\r
+ GetCurrentProcess (), &hProcessDup, PROCESS_ALL_ACCESS,\r
+ FALSE, 0);\r
+\r
+ /* Detect the special case where the process is\r
+ * already dead...\r
+ */\r
+ if (GetExitCodeProcess (bDup ? hProcessDup : hProcess, &dwCode) &&\r
+ (STILL_ACTIVE == dwCode))\r
+ {\r
+ FARPROC pfnExitProc;\r
+\r
+ pfnExitProc = GetProcAddress (hKernel, "ExitProcess");\r
+\r
+ hRT = CreateRemoteThread ((bDup) ? hProcessDup : hProcess, NULL, 0,\r
+ (LPTHREAD_START_ROUTINE) pfnExitProc, (PVOID) uExitCode, 0, &dwTID);\r
+\r
+ dwErr = GetLastError ();\r
+ }\r
+ else\r
+ {\r
+ dwErr = ERROR_PROCESS_ABORTED;\r
+ }\r
+\r
+ if (hRT)\r
+ {\r
+ /* Must wait process to terminate to\r
+ * guarantee that it has exited...\r
+ */\r
+ DWORD dwWaitResult = WaitForSingleObject ((bDup) ? hProcessDup : hProcess,\r
+ dwTimeout);\r
+ if (dwWaitResult == WAIT_TIMEOUT)\r
+ dwErr = WAIT_TIMEOUT;\r
+ else\r
+ dwErr = GetLastError ();\r
+\r
+ CloseHandle (hRT);\r
+ bSuccess = dwErr == NO_ERROR;\r
+ }\r
+\r
+ if (bDup)\r
+ CloseHandle (hProcessDup);\r
+\r
+ SetLastError (dwErr);\r
+\r
+ return bSuccess;\r
+}
+\r
} /* extern "C" */\r
\r
#endif\r