aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLRN <lrn1986@gmail.com>2012-07-12 21:06:27 +0000
committerLRN <lrn1986@gmail.com>2012-07-12 21:06:27 +0000
commit1ddd74011af93e1e166d9de48542b0a23f1e1405 (patch)
treeaa0550b801e72a39899d2a6340a796ec7417083b /src
parent4d1707340ffd21eafab733607b03ef3f433b80ef (diff)
downloadgnunet-1ddd74011af93e1e166d9de48542b0a23f1e1405.tar.gz
gnunet-1ddd74011af93e1e166d9de48542b0a23f1e1405.zip
W32: safer process termination
Diffstat (limited to 'src')
-rw-r--r--src/include/winproc.h1
-rw-r--r--src/util/os_priority.c14
-rw-r--r--src/util/win.cc69
3 files changed, 80 insertions, 4 deletions
diff --git a/src/include/winproc.h b/src/include/winproc.h
index 3670a74b0..6cbe56248 100644
--- a/src/include/winproc.h
+++ b/src/include/winproc.h
@@ -227,6 +227,7 @@ extern "C"
227 int GNInitWinEnv (); 227 int GNInitWinEnv ();
228 void GNShutdownWinEnv (); 228 void GNShutdownWinEnv ();
229 229
230 BOOL SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout);
230#ifdef __cplusplus 231#ifdef __cplusplus
231} 232}
232#endif 233#endif
diff --git a/src/util/os_priority.c b/src/util/os_priority.c
index 173d8814a..b0668e20d 100644
--- a/src/util/os_priority.c
+++ b/src/util/os_priority.c
@@ -461,10 +461,16 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
461 if (0 != GetExitCodeProcess (proc->handle, &exitcode)) 461 if (0 != GetExitCodeProcess (proc->handle, &exitcode))
462 must_kill = (exitcode == STILL_ACTIVE) ? GNUNET_YES : GNUNET_NO; 462 must_kill = (exitcode == STILL_ACTIVE) ? GNUNET_YES : GNUNET_NO;
463 if (GNUNET_YES == must_kill) 463 if (GNUNET_YES == must_kill)
464 if (0 == TerminateProcess (proc->handle, 0)) 464 if (0 == SafeTerminateProcess (proc->handle, 0, 0))
465 { 465 {
466 SetErrnoFromWinError (GetLastError ()); 466 DWORD error_code = GetLastError ();
467 return -1; 467 if (error_code != WAIT_TIMEOUT) /* OK, since timeout is 0 */
468 {
469 LOG (GNUNET_ERROR_TYPE_WARNING,
470 "SafeTermiateProcess failed with code %lu\n", error_code);
471 SetErrnoFromWinError (error_code);
472 return -1;
473 }
468 } 474 }
469 } 475 }
470 return 0; 476 return 0;
@@ -1386,7 +1392,7 @@ start_process (int pipe_control,
1386 /* If we can't pass on the socket(s), the child will block forever, 1392 /* If we can't pass on the socket(s), the child will block forever,
1387 * better put it out of its misery. 1393 * better put it out of its misery.
1388 */ 1394 */
1389 TerminateProcess (gnunet_proc->handle, 0); 1395 SafeTerminateProcess (gnunet_proc->handle, 0, 0);
1390 CloseHandle (gnunet_proc->handle); 1396 CloseHandle (gnunet_proc->handle);
1391 if (NULL != gnunet_proc->control_pipe) 1397 if (NULL != gnunet_proc->control_pipe)
1392 GNUNET_DISK_file_close (gnunet_proc->control_pipe); 1398 GNUNET_DISK_file_close (gnunet_proc->control_pipe);
diff --git a/src/util/win.cc b/src/util/win.cc
index 1f660720e..7b67c9e83 100644
--- a/src/util/win.cc
+++ b/src/util/win.cc
@@ -1261,6 +1261,75 @@ char *winErrorStr(const char *prefix, int dwErr)
1261 return ret; 1261 return ret;
1262} 1262}
1263 1263
1264/**
1265 * Terminate a process by creating a remote thread within it,
1266 * which proceeds to call ExitProcess() inside that process.
1267 * Safer than TerminateProcess ().
1268 *
1269 * Code is from From http://private-storm.de/2009/08/11/case-terminateprocess/
1270 *
1271 * @param hProcess handle of a process to terminate
1272 * @param uExitCode exit code to use for ExitProcess()
1273 * @param dwTimeout number of ms to wait for the process to terminate
1274 * @return TRUE on success, FALSE on failure (check last error for the code)
1275 */
1276BOOL
1277SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout)
1278{
1279 DWORD dwTID, dwCode, dwErr = 0;
1280 HANDLE hProcessDup = INVALID_HANDLE_VALUE;
1281 HANDLE hRT = NULL;
1282 HINSTANCE hKernel = GetModuleHandle ("Kernel32");
1283 BOOL bSuccess = FALSE;
1284
1285 BOOL bDup = DuplicateHandle (GetCurrentProcess (), hProcess,
1286 GetCurrentProcess (), &hProcessDup, PROCESS_ALL_ACCESS,
1287 FALSE, 0);
1288
1289 /* Detect the special case where the process is
1290 * already dead...
1291 */
1292 if (GetExitCodeProcess (bDup ? hProcessDup : hProcess, &dwCode) &&
1293 (STILL_ACTIVE == dwCode))
1294 {
1295 FARPROC pfnExitProc;
1296
1297 pfnExitProc = GetProcAddress (hKernel, "ExitProcess");
1298
1299 hRT = CreateRemoteThread ((bDup) ? hProcessDup : hProcess, NULL, 0,
1300 (LPTHREAD_START_ROUTINE) pfnExitProc, (PVOID) uExitCode, 0, &dwTID);
1301
1302 dwErr = GetLastError ();
1303 }
1304 else
1305 {
1306 dwErr = ERROR_PROCESS_ABORTED;
1307 }
1308
1309 if (hRT)
1310 {
1311 /* Must wait process to terminate to
1312 * guarantee that it has exited...
1313 */
1314 DWORD dwWaitResult = WaitForSingleObject ((bDup) ? hProcessDup : hProcess,
1315 dwTimeout);
1316 if (dwWaitResult == WAIT_TIMEOUT)
1317 dwErr = WAIT_TIMEOUT;
1318 else
1319 dwErr = GetLastError ();
1320
1321 CloseHandle (hRT);
1322 bSuccess = dwErr == NO_ERROR;
1323 }
1324
1325 if (bDup)
1326 CloseHandle (hProcessDup);
1327
1328 SetLastError (dwErr);
1329
1330 return bSuccess;
1331}
1332
1264} /* extern "C" */ 1333} /* extern "C" */
1265 1334
1266#endif 1335#endif