diff options
author | Bertrand Marc <beberking@gmail.com> | 2012-06-06 20:47:48 +0200 |
---|---|---|
committer | Bertrand Marc <beberking@gmail.com> | 2012-06-06 20:47:48 +0200 |
commit | 740b30688bd745a527f96f9116c19acb3480971a (patch) | |
tree | 2709a3f4dba11c174aa9e1ba3612e30c578e76a9 /contrib/timeout_watchdog_w32.c | |
parent | 2b81464a43485fcc8ce079fafdee7b7a171835f4 (diff) |
Imported Upstream version 0.9.3upstream/0.9.3
Diffstat (limited to 'contrib/timeout_watchdog_w32.c')
-rw-r--r-- | contrib/timeout_watchdog_w32.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/contrib/timeout_watchdog_w32.c b/contrib/timeout_watchdog_w32.c new file mode 100644 index 0000000..46a6157 --- /dev/null +++ b/contrib/timeout_watchdog_w32.c @@ -0,0 +1,190 @@ +/* + This file is part of GNUnet + (C) 2010 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file contrib/timeout_watchdog_w32.c + * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period + * @author LRN + */ + +#include <windows.h> +#include <sys/types.h> +#include <stdio.h> + +int +main (int argc, char *argv[]) +{ + int i; + DWORD wait_result; + wchar_t *commandline; + wchar_t **wargv; + wchar_t *arg; + unsigned int cmdlen; + wchar_t *idx; + STARTUPINFOW start; + PROCESS_INFORMATION proc; + + wchar_t wpath[MAX_PATH + 1]; + + wchar_t *pathbuf; + DWORD pathbuf_len, alloc_len; + wchar_t *ptr; + wchar_t *non_const_filename; + wchar_t *wcmd; + int wargc; + int timeout = 0; + + HANDLE job; + + if (argc < 3) + { + printf + ("arg 1: timeout in sec., arg 2: executable, arg<n> arguments\n"); + exit (1); + } + + timeout = atoi (argv[1]); + + if (timeout == 0) + timeout = 600; + + commandline = GetCommandLineW (); + if (commandline == NULL) + { + printf ("Failed to get commandline: %lu\n", GetLastError ()); + exit (2); + } + + wargv = CommandLineToArgvW (commandline, &wargc); + if (wargv == NULL || wargc <= 1) + { + printf ("Failed to get parse commandline: %lu\n", GetLastError ()); + exit (3); + } + + job = CreateJobObject (NULL, NULL); + if (job == NULL) + { + printf ("Failed to create a job: %lu\n", GetLastError ()); + exit (4); + } + + pathbuf_len = GetEnvironmentVariableW (L"PATH", (wchar_t *) &pathbuf, 0); + + alloc_len = pathbuf_len + 1; + + pathbuf = malloc (alloc_len * sizeof (wchar_t)); + + ptr = pathbuf; + + alloc_len = GetEnvironmentVariableW (L"PATH", ptr, pathbuf_len); + + cmdlen = wcslen (wargv[2]); + if (cmdlen < 5 || wcscmp (&wargv[2][cmdlen - 4], L".exe") != 0) + { + non_const_filename = malloc (sizeof (wchar_t) * (cmdlen + 5)); + _snwprintf (non_const_filename, cmdlen + 5, L"%s.exe", wargv[2]); + } + else + { + non_const_filename = wcsdup (wargv[2]); + } + + /* Check that this is the full path. If it isn't, search. */ + if (non_const_filename[1] == L':') + _snwprintf (wpath, sizeof (wpath) / sizeof (wchar_t), L"%s", non_const_filename); + else if (!SearchPathW + (pathbuf, non_const_filename, NULL, sizeof (wpath) / sizeof (wchar_t), + wpath, NULL)) + { + printf ("Failed to get find executable: %lu\n", GetLastError ()); + exit (5); + } + free (pathbuf); + free (non_const_filename); + + cmdlen = wcslen (wpath) + 4; + i = 3; + while (NULL != (arg = wargv[i++])) + cmdlen += wcslen (arg) + 4; + + wcmd = idx = malloc (sizeof (wchar_t) * (cmdlen + 1)); + i = 2; + while (NULL != (arg = wargv[i++])) + { + /* This is to escape trailing slash */ + wchar_t arg_lastchar = arg[wcslen (arg) - 1]; + if (idx == wcmd) + idx += swprintf (idx, L"\"%s%s\" ", wpath, + arg_lastchar == L'\\' ? L"\\" : L""); + else + { + if (wcschr (arg, L' ') != NULL) + idx += swprintf (idx, L"\"%s%s\"%s", arg, + arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" "); + else + idx += swprintf (idx, L"%s%s%s", arg, + arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" "); + } + } + + LocalFree (wargv); + + memset (&start, 0, sizeof (start)); + start.cb = sizeof (start); + + if (!CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED, + NULL, NULL, &start, &proc)) + { + wprintf (L"Failed to get spawn process `%s' with arguments `%s': %lu\n", wpath, wcmd, GetLastError ()); + exit (6); + } + + AssignProcessToJobObject (job, proc.hProcess); + + ResumeThread (proc.hThread); + CloseHandle (proc.hThread); + + free (wcmd); + + wait_result = WaitForSingleObject (proc.hProcess, timeout * 1000); + if (wait_result == WAIT_OBJECT_0) + { + DWORD status; + wait_result = GetExitCodeProcess (proc.hProcess, &status); + CloseHandle (proc.hProcess); + if (wait_result != 0) + { + printf ("Test process exited with result %lu\n", status); + TerminateJobObject (job, status); + exit (status); + } + printf ("Test process exited (failed to obtain exit status)\n"); + TerminateJobObject (job, 0); + exit (0); + } + printf ("Child processes were killed after timeout of %u seconds\n", + timeout); + TerminateJobObject (job, 1); + CloseHandle (proc.hProcess); + exit (1); +} + +/* end of timeout_watchdog_w32.c */ |