From adbe5a2f2e835718a6e6a5d152c0cf2ca41a6ac1 Mon Sep 17 00:00:00 2001 From: Manoj Ampalam Date: Fri, 13 Jan 2017 13:25:31 -0800 Subject: [PATCH] Fixed issue: sshd service terminates after a brief period of time (https://github.com/PowerShell/Win32-OpenSSH/issues/241) --- contrib/win32/win32compat/misc.c | 5 ++- contrib/win32/win32compat/signal.c | 2 +- contrib/win32/win32compat/signal_internal.h | 7 +++- contrib/win32/win32compat/signal_sigchld.c | 42 +++++++++++++-------- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index 43d180a57..224baccf1 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -472,14 +472,15 @@ settimes(wchar_t * path, FILETIME *cretime, FILETIME *acttime, FILETIME *modtime NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (handle == INVALID_HANDLE_VALUE) { - errno = GetLastError; + /* TODO - convert Win32 error to errno */ + errno = GetLastError(); debug("w32_settimes - CreateFileW ERROR:%d", errno); return -1; } if (SetFileTime(handle, cretime, acttime, modtime) == 0) { - errno = GetLastError; + errno = GetLastError(); debug("w32_settimes - SetFileTime ERROR:%d", errno); CloseHandle(handle); return -1; diff --git a/contrib/win32/win32compat/signal.c b/contrib/win32/win32compat/signal.c index 8a74da9a3..d84f5412f 100644 --- a/contrib/win32/win32compat/signal.c +++ b/contrib/win32/win32compat/signal.c @@ -258,7 +258,7 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds) if ((ret >= WAIT_OBJECT_0) && (ret <= WAIT_OBJECT_0 + num_all_events - 1)) { //woken up by event signalled /* is this due to a child process going down*/ - if (children.num_children && ((ret - WAIT_OBJECT_0) < children.num_children)) { + if (live_children && ((ret - WAIT_OBJECT_0) < live_children)) { sigaddset(&pending_signals, W32_SIGCHLD); sw_child_to_zombie(ret - WAIT_OBJECT_0); } diff --git a/contrib/win32/win32compat/signal_internal.h b/contrib/win32/win32compat/signal_internal.h index 826ca9574..4bd7f2093 100644 --- a/contrib/win32/win32compat/signal_internal.h +++ b/contrib/win32/win32compat/signal_internal.h @@ -11,12 +11,17 @@ int sw_kill(int pid, int sig); /* child processes */ #define MAX_CHILDREN 50 struct _children { + /* + * array of handles and process_ids. + * intial (num_children - num_zombies) are alive + * rest are zombies + */ HANDLE handles[MAX_CHILDREN]; DWORD process_id[MAX_CHILDREN]; /* total children */ DWORD num_children; /* #zombies */ - /* (num_chileren - zombies) are live children */ + /* (num_children - zombies) are live children */ DWORD num_zombies; }; diff --git a/contrib/win32/win32compat/signal_sigchld.c b/contrib/win32/win32compat/signal_sigchld.c index afd0242f4..53c6c2d76 100644 --- a/contrib/win32/win32compat/signal_sigchld.c +++ b/contrib/win32/win32compat/signal_sigchld.c @@ -101,7 +101,7 @@ sw_remove_child_at_index(DWORD index) { int sw_child_to_zombie(DWORD index) { - DWORD last_non_zombie, last_child, zombie_pid; + DWORD last_non_zombie, zombie_pid; HANDLE zombie_handle; debug("zombie'ing child at index %d, %d zombies of %d", index, @@ -112,17 +112,17 @@ sw_child_to_zombie(DWORD index) { return -1; } - zombie_pid = children.process_id[index]; - zombie_handle = children.handles[index]; last_non_zombie = children.num_children - children.num_zombies - 1; - last_child = children.num_children - 1; - - children.handles[index] = children.handles[last_non_zombie]; - children.process_id[index] = children.process_id[last_non_zombie]; - - children.handles[last_non_zombie] = children.handles[index]; - children.process_id[last_non_zombie] = children.process_id[index]; - + + if (last_non_zombie != index) { + /* swap */ + zombie_pid = children.process_id[index]; + zombie_handle = children.handles[index]; + children.handles[index] = children.handles[last_non_zombie]; + children.process_id[index] = children.process_id[last_non_zombie]; + children.handles[last_non_zombie] = zombie_handle; + children.process_id[last_non_zombie] = zombie_pid; + } children.num_zombies++; return 0; } @@ -185,10 +185,13 @@ int waitpid(int pid, int *status, int options) { return -1; } - process = children.handles[index]; - ret = WaitForSingleObject(process, INFINITE); - if (ret != WAIT_OBJECT_0) - DebugBreak();//fatal + /* wait if process is still alive */ + if (index < children.num_children - children.num_zombies) { + process = children.handles[index]; + ret = WaitForSingleObject(process, INFINITE); + if (ret != WAIT_OBJECT_0) + DebugBreak();//fatal + } ret_id = children.process_id[index]; GetExitCodeProcess(process, &exit_code); @@ -200,6 +203,15 @@ int waitpid(int pid, int *status, int options) { } /* pid = -1*/ + /* are there any existing zombies */ + if (children.num_zombies) { + /* return one of them */ + ret_id = children.process_id[children.num_children - 1]; + sw_remove_child_at_index(children.num_children - 1); + return ret_id; + } + + /* all children are alive. wait for one of them to exit */ timeout = INFINITE; if (options & WNOHANG) timeout = 0;