From: Eric Pouech eric.pouech@gmail.com
--- configure.ac | 2 + dlls/kernelbase/console.c | 18 ++- dlls/kernelbase/process.c | 1 + dlls/kernelbase/thread.c | 1 + dlls/ntdll/loader.c | 5 +- dlls/ntdll/unix/process.c | 1 + dlls/ntdll/unix/thread.c | 1 + programs/conhost/conhost.c | 4 +- programs/conhost/window.c | 6 + programs/timeout/Makefile.in | 8 ++ programs/timeout/main.c | 187 +++++++++++++++++++++++++++++ programs/timeout/tests/Makefile.in | 4 + programs/timeout/tests/timeout.c | 161 +++++++++++++++++++++++++ programs/timeout/timeout.h | 29 +++++ programs/timeout/timeout.rc | 34 ++++++ server/process.c | 3 + 16 files changed, 460 insertions(+), 5 deletions(-) create mode 100644 programs/timeout/Makefile.in create mode 100644 programs/timeout/main.c create mode 100644 programs/timeout/tests/Makefile.in create mode 100644 programs/timeout/tests/timeout.c create mode 100644 programs/timeout/timeout.h create mode 100644 programs/timeout/timeout.rc
diff --git a/configure.ac b/configure.ac index 6596f653fb1..7b5b84bf8c8 100644 --- a/configure.ac +++ b/configure.ac @@ -3521,6 +3521,8 @@ WINE_CONFIG_MAKEFILE(programs/tasklist) WINE_CONFIG_MAKEFILE(programs/tasklist/tests) WINE_CONFIG_MAKEFILE(programs/taskmgr) WINE_CONFIG_MAKEFILE(programs/termsv) +WINE_CONFIG_MAKEFILE(programs/timeout) +WINE_CONFIG_MAKEFILE(programs/timeout/tests) WINE_CONFIG_MAKEFILE(programs/uninstaller) WINE_CONFIG_MAKEFILE(programs/unlodctr) WINE_CONFIG_MAKEFILE(programs/view) diff --git a/dlls/kernelbase/console.c b/dlls/kernelbase/console.c index 97c5462c42f..ecf2203e0f5 100644 --- a/dlls/kernelbase/console.c +++ b/dlls/kernelbase/console.c @@ -71,11 +71,17 @@ struct ctrl_handler
static BOOL WINAPI default_ctrl_handler( DWORD type ) { - FIXME( "Terminating process %lx on event %lx\n", GetCurrentProcessId(), type ); + MESSAGE("%04lx:%04lx:Terminating process %lx on event %lx\n", GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentProcessId(), type ); if (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT) + { + MESSAGE("%04lx:%04lx:%08lx\n", GetCurrentProcessId(), GetCurrentThreadId(), STATUS_CONTROL_C_EXIT ); RtlExitUserProcess( STATUS_CONTROL_C_EXIT ); + } else + { + MESSAGE("%04lx:%04lx:0\n", GetCurrentProcessId(), GetCurrentThreadId() ); RtlExitUserProcess( 0 ); + } return TRUE; }
@@ -533,7 +539,8 @@ DWORD WINAPI CtrlRoutine( void *arg ) DWORD_PTR event = (DWORD_PTR)arg; struct ctrl_handler *handler;
- if (event == CTRL_C_EVENT) + MESSAGE("%04lx:%04lx:Here with %Ix\n", GetCurrentProcessId(), GetCurrentThreadId(), event); + if (event == CTRL_C_EVENT && IsDebuggerPresent()) { BOOL caught_by_dbg = TRUE; /* First, try to pass the ctrl-C event to the debugger (if any) @@ -549,9 +556,14 @@ DWORD WINAPI CtrlRoutine( void *arg ) caught_by_dbg = FALSE; } __ENDTRY - if (caught_by_dbg) return 0; + if (caught_by_dbg) + { + MESSAGE("%04lx:%04lx:Caught by debugger\n", GetCurrentProcessId(), GetCurrentThreadId()); + return 0; + } }
+ MESSAGE("%04lx:%04lx:CF %lx\n", GetCurrentProcessId(), GetCurrentThreadId(), NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags); if (NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags & 1) return 0;
RtlEnterCriticalSection( &console_section ); diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index df3447a9014..ff4fb2b24d0 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -1288,6 +1288,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH TerminateProcess( HANDLE handle, DWORD exit_code ) SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } + MESSAGE("%04lx:%s %p %lu\n", GetCurrentThreadId(), __FUNCTION__, handle, exit_code); return set_ntstatus( NtTerminateProcess( handle, exit_code )); }
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index 12e1777262a..cfa43b514fc 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -647,6 +647,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH SwitchToThread(void) */ BOOL WINAPI DECLSPEC_HOTPATCH TerminateThread( HANDLE handle, DWORD exit_code ) { + MESSAGE("%04lx:%s %p %lu\n", GetCurrentThreadId(), __FUNCTION__, handle, exit_code); return set_ntstatus( NtTerminateThread( handle, exit_code )); }
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 0c25fe14133..459e875c11b 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -3314,7 +3314,10 @@ done: */ NTSTATUS WINAPI __wine_ctrl_routine( void *arg ) { - DWORD ret = pCtrlRoutine ? pCtrlRoutine( arg ) : 0; + DWORD ret; + + MESSAGE("%04lx:%04lx:Here with %p and %p\n", GetCurrentProcessId(), GetCurrentThreadId(), arg, pCtrlRoutine); + ret = pCtrlRoutine ? pCtrlRoutine( arg ) : 0; RtlExitUserThread( ret ); }
diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index c3a730379a4..6f1e65a0e6a 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -996,6 +996,7 @@ NTSTATUS WINAPI NtTerminateProcess( HANDLE handle, LONG exit_code ) unsigned int ret; BOOL self;
+ MESSAGE("%04x:%s %p %u\n", GetCurrentThreadId(), __FUNCTION__, handle, exit_code); SERVER_START_REQ( terminate_process ) { req->handle = wine_server_obj_handle( handle ); diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index cec6b3cb106..9aa6cd6f25d 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1690,6 +1690,7 @@ NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code ) unsigned int ret; BOOL self;
+ MESSAGE("%04x:%s %p %u\n", GetCurrentThreadId(), __FUNCTION__, handle, exit_code); SERVER_START_REQ( terminate_thread ) { req->handle = wine_server_obj_handle( handle ); diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c index 708696100d0..096e5a11fec 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -2910,13 +2910,14 @@ static int main_loop( struct console *console, HANDLE signal ) EnterCriticalSection( &console_section ); status = process_console_ioctls( console ); LeaveCriticalSection( &console_section ); - if (status) return 0; + if (status) {MESSAGE("%04lx:leave %s:%u %lx\n", GetCurrentThreadId(), __FILE__, __LINE__, status); return 0;} break;
case WAIT_OBJECT_0 + 1: if (signal_io.Status || signal_io.Information != sizeof(signal_id)) { TRACE( "signaled quit\n" ); + MESSAGE("%04lx:leave signaled quit %s:%u\n", GetCurrentThreadId(), __FILE__, __LINE__); return 0; } FIXME( "unimplemented signal %x\n", signal_id ); @@ -2927,6 +2928,7 @@ static int main_loop( struct console *console, HANDLE signal )
default: TRACE( "wait failed, quit\n"); + MESSAGE("%04lx:leave wait failed %s:%u\n", GetCurrentThreadId(), __FILE__, __LINE__); return 0; } } diff --git a/programs/conhost/window.c b/programs/conhost/window.c index 9817c5fdac9..c468dbf9106 100644 --- a/programs/conhost/window.c +++ b/programs/conhost/window.c @@ -911,7 +911,13 @@ static void set_first_font( struct console *console, struct console_config *conf }
if (fc.pass > 5) + { ERR("Unable to find a valid console font\n"); +#if 0 + console->active->font.width = + console->active->font.height = 1; +#endif + }
/* Update active configuration */ config->cell_width = console->active->font.width; diff --git a/programs/timeout/Makefile.in b/programs/timeout/Makefile.in new file mode 100644 index 00000000000..708cca355ff --- /dev/null +++ b/programs/timeout/Makefile.in @@ -0,0 +1,8 @@ +MODULE = timeout.exe +IMPORTS = user32 + +EXTRADLLFLAGS = -mconsole -municode + +SOURCES = \ + timeout.rc \ + main.c diff --git a/programs/timeout/main.c b/programs/timeout/main.c new file mode 100644 index 00000000000..0ac5f8fab15 --- /dev/null +++ b/programs/timeout/main.c @@ -0,0 +1,187 @@ +/* + * Copyright 2024 Michele Dionisio michele.dionisio@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <windows.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <synchapi.h> +#include <stdbool.h> +#include <wchar.h> +#include <conio.h> +#include "timeout.h" + +static int WINAPIV timeout_error_wprintf(int msg, ...) +{ + WCHAR msg_buffer[MAXSTRING]; + va_list va_args; + int ret; + + LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer)); + va_start(va_args, msg); + ret = vfwprintf(stderr, msg_buffer, va_args); + va_end(va_args); + return ret; +} + +static int WINAPIV timeout_message(int msg) +{ + WCHAR msg_buffer[MAXSTRING]; + + LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer)); + return fwprintf(stdout, msg_buffer); +} + +static int WINAPIV timeout_wprintf(int msg, ...) +{ + WCHAR msg_buffer[MAXSTRING]; + va_list va_args; + int ret; + + LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer)); + va_start(va_args, msg); + ret = vfwprintf(stdout, msg_buffer, va_args); + va_end(va_args); + return ret; +} + +static volatile LONG stop; + +static BOOL WINAPI ctrl_c_handler(DWORD dwCtrlType) +{ + switch (dwCtrlType) + { + case CTRL_BREAK_EVENT: + case CTRL_C_EVENT: + case 0x8765ABCD: + InterlockedOr(&stop, 1); + return TRUE; + } + return FALSE; +} + +static BOOL WINAPI parseTime(const WCHAR *in, int *out) +{ + WCHAR *endptr = NULL; + long l_wait_time; + l_wait_time = wcstol(in, &endptr, 10); + if (*endptr != L'\0') { + return FALSE; + } + if ((l_wait_time < -1) || (l_wait_time > 99999)) + { + return FALSE; + } + *out = (int)l_wait_time; + return TRUE; +} + +int __cdecl wmain(int argc, WCHAR *argv[]) +{ + DWORD dummy; + int wait_time = 0; + int wait_time_valid = 0; + bool nobreak = false; + int ret = 0; + int i; + + if (argc <= 1) + { + timeout_error_wprintf(STRING_BAD_COMMAND_LINE); + return 1; + } + + for (i = 1; i < argc; i++) + { + if (wcscmp(argv[i], L"/?") == 0) + { + timeout_message(STRING_USAGE); + return 0; + } + else if ((wcsicmp(argv[i], L"/t") == 0) && (wait_time_valid == 0)) + { + if ((i + 1) < argc) + { + i++; + if (!parseTime(argv[i], &wait_time)) + { + timeout_error_wprintf(STRING_TIMEOUT_INVALID); + return 1; + } + wait_time_valid = 1; + } + else + { + timeout_error_wprintf(STRING_BAD_COMMAND_LINE); + return 1; + } + } + else if (wcsicmp(argv[i], L"/nobreak") == 0) + { + nobreak = true; + } + else if (wait_time_valid == 0) + { + if (!parseTime(argv[i], &wait_time)) + { + timeout_error_wprintf(STRING_TIMEOUT_INVALID); + return 1; + } + wait_time_valid = 1; + } + else + { + timeout_error_wprintf(STRING_BAD_COMMAND_LINE); + return 1; + } + } + + if (wait_time_valid == 0) + { + timeout_error_wprintf(STRING_BAD_COMMAND_LINE); + return 1; + } + + if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dummy)) + { + timeout_error_wprintf(STRING_ERROR_REDIRECT); + return 101; + } + + if (nobreak) + { + SetConsoleCtrlHandler(ctrl_c_handler, TRUE); + } + + for (i = 0; (wait_time < 0) || (i < wait_time); i++) + { + timeout_wprintf(STRING_WAITING_SINCE, i); + timeout_message(nobreak ? STRING_PRESS_CTRLC : STRING_PRESS_KEY); + if (InterlockedOr(&stop, 0)) + { + ret = 1; + break; + } + if (!nobreak && _kbhit()) + break; + Sleep(1000); + } + putc('\n', stdout); + + return ret; +} diff --git a/programs/timeout/tests/Makefile.in b/programs/timeout/tests/Makefile.in new file mode 100644 index 00000000000..a50cdee3062 --- /dev/null +++ b/programs/timeout/tests/Makefile.in @@ -0,0 +1,4 @@ +TESTDLL = timeout.exe + +SOURCES = \ + timeout.c diff --git a/programs/timeout/tests/timeout.c b/programs/timeout/tests/timeout.c new file mode 100644 index 00000000000..124338dd154 --- /dev/null +++ b/programs/timeout/tests/timeout.c @@ -0,0 +1,161 @@ +/* + * Copyright 2024 Michele Dionisio michele.dionisio@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <windows.h> +#include "wine/test.h" + +static DWORD run_timeout_stdin(const char *commandline) +{ + PROCESS_INFORMATION process_info = {0}; + STARTUPINFOA startup_info; + char cmd[4096]; + DWORD exitcode; + + memset(&startup_info, 0, sizeof(startup_info)); + startup_info.cb = sizeof(startup_info); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = NULL; + startup_info.hStdError = NULL; + + sprintf(cmd, "timeout.exe %s", commandline); + + CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &startup_info, &process_info); + + WaitForSingleObject(process_info.hProcess, INFINITE); + GetExitCodeProcess(process_info.hProcess, &exitcode); + CloseHandle(process_info.hProcess); + CloseHandle(process_info.hThread); + return exitcode; +} + +static void test_basic(void) +{ + DWORD exit_code; + + /* No options */ + exit_code = run_timeout_stdin(""); + ok(exit_code == 1, "Unexpected exit_code %lu\n", exit_code); + + /* /? */ + exit_code = run_timeout_stdin("/?"); + ok(exit_code == 0, "Unexpected exit_code %lu\n", exit_code); + + /* /T 1 /NOBREAK */ + exit_code = run_timeout_stdin("/T 1 /NOBREAK"); + ok(exit_code == 0, "Unexpected exit_code %lu\n", exit_code); + + /* /T 1 */ + exit_code = run_timeout_stdin("/T 1"); + ok(exit_code == 0, "Unexpected exit_code %lu\n", exit_code); + + /* 1 /NOBREAK */ + exit_code = run_timeout_stdin("1 /NOBREAK"); + ok(exit_code == 0, "Unexpected exit_code %lu\n", exit_code); + + /* /T 1ab /NOBREAK */ + exit_code = run_timeout_stdin("/T 1ab /NOBREAK"); + ok(exit_code == 1, "Unexpected exit_code %lu\n", exit_code); + + /* /T -3 /NOBREAK */ + exit_code = run_timeout_stdin("/T -3 /NOBREAK"); + ok(exit_code == 1, "Unexpected exit_code %lu\n", exit_code); + + /* /T 10000000 /NOBREAK */ + exit_code = run_timeout_stdin("/T 10000000 /NOBREAK"); + ok(exit_code == 1, "Unexpected exit_code %lu\n", exit_code); +} + +#define run_timeout_ctrlc(a, b) _run_timeout_ctrlc(__FILE__, __LINE__, a, b) +static void _run_timeout_ctrlc(const char *file, int line, const char *option, DWORD exitcode_expected) +{ + PROCESS_INFORMATION process_info = {0}; + STARTUPINFOA startup_info; + char cmd[4096]; + DWORD status, exitcode; + DWORD64 tick_count; + BOOL ret; + + memset(&startup_info, 0, sizeof(startup_info)); + startup_info.cb = sizeof(startup_info); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = NULL; + startup_info.hStdError = NULL; + + SetConsoleCtrlHandler(NULL, FALSE); + sprintf(cmd, "timeout.exe /T 12 %s", option); + ret = CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &startup_info, &process_info); + ok(ret, "CreateProcessA failed: %lu\n", GetLastError()); + + ok(0, "child created for '%s' %04lx\n", option, process_info.dwProcessId); + /* wait for process to be started */ + status = WaitForSingleObject(process_info.hProcess, 2000); + ok_(file, line)(status == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx (expecting WAIT_TIMEOUT)\n", status); + + tick_count = GetTickCount64(); + + SetConsoleCtrlHandler(NULL, TRUE); + ret = GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + ok_(file, line)(ret, "GenerateConsoleCtrlEvent failed: %lu\n", GetLastError()); + + status = WaitForSingleObject(process_info.hProcess, INFINITE); + ok_(file, line)(status == WAIT_OBJECT_0, "WaitForSingleObject returned %#lx (expecting WAIT_OBJECT_0)\n", status); + + tick_count = GetTickCount64() - tick_count; + ok_(file, line)(tick_count < 2000, "Process has not been stopped by ctrl-c\n"); + + ret = GetExitCodeProcess(process_info.hProcess, &exitcode); + ok_(file, line)(ret, "GetExitCodeProcess failed\n"); + + CloseHandle(process_info.hProcess); + CloseHandle(process_info.hThread); + ok_(file, line)(exitcode == exitcode_expected, "Expected exitcode %ld, got %lx\n", + exitcode_expected, exitcode); +} + +static void test_ctrlc(void) +{ + run_timeout_ctrlc("", STATUS_CONTROL_C_EXIT); + run_timeout_ctrlc("/nobreak", 1); +} + +START_TEST(timeout) +{ + BOOL ret; + /* always run on a separate console, so that: + * - we're sure to have a valid console input handle (no Wine unix console...) + * - we can send ctrl-c events without interfering with parent (winetest...) + */ + ret = FreeConsole(); + ok(ret, "FreeConsole() failed\n"); + SetStdHandle(STD_INPUT_HANDLE, NULL); /* will force reallocation of std handle in AllocConsole() */ + SetStdHandle(STD_OUTPUT_HANDLE, NULL); /* will force reallocation of std handle in AllocConsole() */ + SetStdHandle(STD_ERROR_HANDLE, NULL); /* will force reallocation of std handle in AllocConsole() */ + ret = AllocConsole(); + ok(ret, "AllocConsole() failed\n"); + + if (broken(run_timeout_stdin("/T 0") == 1)) /* Win7 */ + { + win_skip("Skipping tests on Windows 7\n"); + return; + } + + test_basic(); + test_ctrlc(); +} diff --git a/programs/timeout/timeout.h b/programs/timeout/timeout.h new file mode 100644 index 00000000000..346f69fea56 --- /dev/null +++ b/programs/timeout/timeout.h @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Michele Dionisio michele.dionisio@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <windef.h> + +#define MAXSTRING 8192 + +#define STRING_USAGE 101 +#define STRING_BAD_COMMAND_LINE 102 +#define STRING_WAITING_SINCE 103 +#define STRING_PRESS_CTRLC 104 +#define STRING_PRESS_KEY 105 +#define STRING_ERROR_REDIRECT 106 +#define STRING_TIMEOUT_INVALID 107 diff --git a/programs/timeout/timeout.rc b/programs/timeout/timeout.rc new file mode 100644 index 00000000000..70abf9cd6dc --- /dev/null +++ b/programs/timeout/timeout.rc @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Michele Dionisio michele.dionisio@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "timeout.h" + +#pragma makedep po + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE +{ + STRING_USAGE, "Usage: timeout /T <timeout> [</NOBREAK>]\n" + STRING_BAD_COMMAND_LINE, "TIMEOUT: Bad command line\n" + STRING_WAITING_SINCE, "waiting since %d sec. " + STRING_PRESS_CTRLC, "press CTRL+C...\r" + STRING_PRESS_KEY, "press a key to continue...\r" + STRING_ERROR_REDIRECT, "ERROR: not possible to redirect input\n" + STRING_TIMEOUT_INVALID, "ERROR: Timeout value out of range or invalid number. Valid range is -1 to 99999.\n" +} diff --git a/server/process.c b/server/process.c index e06350f7311..8bbd1ee36a8 100644 --- a/server/process.c +++ b/server/process.c @@ -914,6 +914,7 @@ static void terminate_process( struct process *process, struct thread *skip, int struct thread *thread;
grab_object( process ); /* make sure it doesn't get freed when threads die */ + fprintf(stderr, "%s %x %d %d\n", __FUNCTION__, process->id, exit_code, process->is_terminating); process->is_terminating = 1;
restart: @@ -943,6 +944,7 @@ static void kill_all_processes(void) /* kill all processes being attached to a console renderer */ void kill_console_processes( struct thread *renderer, int exit_code ) { + fprintf(stderr, "%s %u %d\n", __FUNCTION__, renderer->id, exit_code); for (;;) /* restart from the beginning of the list every time */ { struct process *process; @@ -1462,6 +1464,7 @@ DECL_HANDLER(terminate_process) } else process = (struct process *)grab_object( current->process );
+ fprintf(stderr, "%s %x %d\n", __FUNCTION__, process->id, req->exit_code); reply->self = (current->process == process); terminate_process( process, current, req->exit_code ); release_object( process );