diff options
author | LRN <lrn1986@gmail.com> | 2012-07-12 21:06:27 +0000 |
---|---|---|
committer | LRN <lrn1986@gmail.com> | 2012-07-12 21:06:27 +0000 |
commit | 1ddd74011af93e1e166d9de48542b0a23f1e1405 (patch) | |
tree | aa0550b801e72a39899d2a6340a796ec7417083b /src | |
parent | 4d1707340ffd21eafab733607b03ef3f433b80ef (diff) | |
download | gnunet-1ddd74011af93e1e166d9de48542b0a23f1e1405.tar.gz gnunet-1ddd74011af93e1e166d9de48542b0a23f1e1405.zip |
W32: safer process termination
Diffstat (limited to 'src')
-rw-r--r-- | src/include/winproc.h | 1 | ||||
-rw-r--r-- | src/util/os_priority.c | 14 | ||||
-rw-r--r-- | src/util/win.cc | 69 |
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 | */ | ||
1276 | BOOL | ||
1277 | SafeTerminateProcess (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 |