Missing SIGCHLD zombie logic

This commit is contained in:
manojampalam 2016-03-28 21:37:06 -07:00
parent 327f077231
commit 56ad915376
7 changed files with 375 additions and 279 deletions

View File

@ -147,7 +147,9 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\fileio.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\fileio.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\termio.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\termio.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\misc.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\misc.c" />
<ClCompile Include="..\win32compat\w32log.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_sigalrm.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_sigchld.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32log.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
@ -163,8 +165,9 @@
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\w32posix.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\w32posix.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\poll.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\poll.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\sys\statvfs.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\sys\statvfs.h" />
<ClInclude Include="..\win32compat\inc\dlfcn.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\dlfcn.h" />
<ClInclude Include="..\win32compat\inc\syslog.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\syslog.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_internal.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -7,7 +7,9 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\fileio.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\fileio.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\termio.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\termio.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\misc.c" /> <ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\misc.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\log.c" /> <ClCompile Include="..\win32compat\w32log.c" />
<ClCompile Include="..\win32compat\signal_sigchld.c" />
<ClCompile Include="..\win32compat\signal_sigalrm.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" /> <ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
@ -53,6 +55,7 @@
<ClInclude Include="..\win32compat\inc\dlfcn.h"> <ClInclude Include="..\win32compat\inc\dlfcn.h">
<Filter>inc</Filter> <Filter>inc</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\win32compat\signal_internal.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="inc"> <Filter Include="inc">

View File

@ -31,7 +31,7 @@
#include "w32fd.h" #include "w32fd.h"
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include "inc\defs.h" #include "signal_internal.h"
/* pending signals to be processed */ /* pending signals to be processed */
sigset_t pending_signals; sigset_t pending_signals;
@ -96,261 +96,7 @@ sw_init_signal_handler_table() {
memset(sig_handlers, 0, sizeof(sig_handlers)); memset(sig_handlers, 0, sizeof(sig_handlers));
} }
/* child processes */ extern struct _children children;
#define MAX_CHILDREN 50
struct _children {
HANDLE handles[MAX_CHILDREN];
DWORD process_id[MAX_CHILDREN];
/* total children */
DWORD num_children;
/* #zombies */
/* (num_chileren - zombies) are live children */
DWORD num_zombies;
} children;
int
sw_add_child(HANDLE child, DWORD pid) {
DWORD first_zombie_index;
debug("Register child %p pid %d, %d zombies of %d", child, pid,
children.num_zombies, children.num_children);
if (children.num_children == MAX_CHILDREN) {
errno = ENOMEM;
return -1;
}
if (children.num_zombies) {
first_zombie_index = children.num_children - children.num_zombies;
children.handles[children.num_children] = children.handles[first_zombie_index];
children.process_id[children.num_children] = children.handles[first_zombie_index];
children.handles[first_zombie_index] = child;
children.process_id[first_zombie_index] = pid;
}
else {
children.handles[children.num_children] = child;
children.process_id[children.num_children] = pid;
}
children.num_children++;
return 0;
}
int
sw_remove_child_at_index(DWORD index) {
DWORD last_non_zombie;
debug("Unregister child at index %d, %d zombies of %d", index,
children.num_zombies, children.num_children);
if ((index >= children.num_children)
|| (children.num_children == 0) ){
errno = EINVAL;
return -1;
}
CloseHandle(children.handles[index]);
if (children.num_zombies == 0) {
children.handles[index] = children.handles[children.num_children - 1];
children.process_id[index] = children.process_id[children.num_children - 1];
}
else {
/* if its a zombie */
if (index >= (children.num_children - children.num_zombies)) {
children.handles[index] = children.handles[children.num_children - 1];
children.process_id[index] = children.handles[children.num_children - 1];
children.num_zombies--;
}
else {
last_non_zombie = children.num_children - children.num_zombies - 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[children.num_children - 1];
children.process_id[last_non_zombie] = children.handles[children.num_children - 1];
}
}
children.num_children--;
return 0;
}
int
sw_child_to_zombie(DWORD index) {
DWORD last_non_zombie;
debug("zombie'ing child at index %d, %d zombies of %d", index,
children.num_zombies, children.num_children);
if (index >= children.num_children) {
errno = EINVAL;
return -1;
}
/* TODO - turn child to zombie*/
return 0;
}
int
sw_remove_child(HANDLE child) {
HANDLE* handles = children.handles;
DWORD num_children = children.num_children;
while (num_children) {
if (*handles == child)
return sw_remove_child_at_index(children.num_children - num_children);
handles++;
num_children--;
}
errno = EINVAL;
return -1;
}
int waitpid(int pid, int *status, int options) {
DWORD index, ret, ret_id, exit_code, timeout = 0;
HANDLE process = NULL;
if (options & (~WNOHANG)) {
errno = ENOTSUP;
DebugBreak();
return -1;
}
if ((pid < -1) || (pid == 0)) {
errno = ENOTSUP;
DebugBreak();
return -1;
}
if (children.num_children == 0) {
errno = ECHILD;
return -1;
}
if (pid > 0) {
if (options != 0) {
errno = ENOTSUP;
DebugBreak();
return -1;
}
/* find entry in table */
for (index = 0; index < children.num_children; index++)
if (children.process_id[index] == pid)
break;
if (index == children.num_children) {
errno = ECHILD;
return -1;
}
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);
CloseHandle(process);
sw_remove_child_at_index(index);
if (status)
*status = exit_code;
return ret_id;
}
/* pid = -1*/
timeout = INFINITE;
if (options & WNOHANG)
timeout = 0;
ret = WaitForMultipleObjects(children.num_children, children.handles, FALSE, timeout);
if ((ret >= WAIT_OBJECT_0) && (ret < (WAIT_OBJECT_0 + children.num_children))) {
index = ret - WAIT_OBJECT_0;
process = children.handles[index];
ret_id = children.process_id[index];
GetExitCodeProcess(process, &exit_code);
CloseHandle(process);
sw_remove_child_at_index(index);
if (status)
*status = exit_code;
return ret_id;
}
else if (ret == WAIT_TIMEOUT) {
/* assert that WNOHANG was specified*/
return 0;
}
DebugBreak();//fatal
return -1;
}
static void
sw_cleanup_child_zombies() {
int pid = 1;
while (pid > 0) {
pid = waitpid(-1, NULL, WNOHANG);
}
}
struct {
HANDLE timer;
ULONGLONG ticks_at_start; /* 0 if timer is not live */
__int64 run_time_sec; /* time in seconds, timer is set to go off from ticks_at_start */
} timer_info;
VOID CALLBACK
sigalrm_APC(
_In_opt_ LPVOID lpArgToCompletionRoutine,
_In_ DWORD dwTimerLowValue,
_In_ DWORD dwTimerHighValue
) {
sigaddset(&pending_signals, W32_SIGALRM);
}
unsigned int
sw_alarm(unsigned int sec) {
LARGE_INTEGER due;
ULONGLONG sec_passed;
int ret = 0;
errno = 0;
/* cancel any live timer if seconds is 0*/
if (sec == 0) {
CancelWaitableTimer(timer_info.timer);
timer_info.ticks_at_start = 0;
timer_info.run_time_sec = 0;
return 0;
}
due.QuadPart = -10000000LL; //1 sec in 100 nanosec intervals
due.QuadPart *= sec;
/* this call resets the timer if it is already active */
if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) {
debug("alram() - ERROR SetWaitableTimer() %d", GetLastError());
return 0;;
}
/* if timer was already ative, return when it was due */
if (timer_info.ticks_at_start) {
sec_passed = (GetTickCount64() - timer_info.ticks_at_start) / 1000;
if (sec_passed < timer_info.run_time_sec)
ret = timer_info.run_time_sec - sec_passed;
}
timer_info.ticks_at_start = GetTickCount64();
timer_info.run_time_sec = sec;
return ret;
}
static int
sw_init_timer() {
memset(&timer_info, 0, sizeof(timer_info));
timer_info.timer = CreateWaitableTimer(NULL, TRUE, NULL);
if (timer_info.timer == NULL) {
errno = ENOMEM;
return -1;
}
return 0;
}
sighandler_t sighandler_t
sw_signal(int signum, sighandler_t handler) { sw_signal(int signum, sighandler_t handler) {
@ -377,7 +123,7 @@ sw_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
int int
sw_raise(int sig) { sw_raise(int sig) {
if (sig == W32_SIGSEGV) if (sig == W32_SIGSEGV)
raise(SIGSEGV); /* raise native exception handler*/ return raise(SIGSEGV); /* raise native exception handler*/
if (sig >= W32_SIGMAX) { if (sig >= W32_SIGMAX) {
errno = EINVAL; errno = EINVAL;
@ -448,6 +194,11 @@ sw_process_pending_signals() {
sw_raise(exp[i]); sw_raise(exp[i]);
sig_int = TRUE; sig_int = TRUE;
} }
else { /* W32_SIG_IGN */
/* for SIGCHLD process zombies */
if (exp[i] == W32_SIGCHLD)
sw_cleanup_child_zombies();
}
sigdelset(&pending_tmp, exp[i]); sigdelset(&pending_tmp, exp[i]);
} }
@ -485,8 +236,9 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
{ {
HANDLE all_events[MAXIMUM_WAIT_OBJECTS]; HANDLE all_events[MAXIMUM_WAIT_OBJECTS];
DWORD num_all_events; DWORD num_all_events;
DWORD live_children = children.num_children - children.num_zombies;
num_all_events = num_events + children.num_children; num_all_events = num_events + live_children;
if (num_all_events > MAXIMUM_WAIT_OBJECTS) { if (num_all_events > MAXIMUM_WAIT_OBJECTS) {
errno = ENOTSUP; errno = ENOTSUP;
@ -497,8 +249,8 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
if (pending_signals) if (pending_signals)
DebugBreak(); DebugBreak();
memcpy(all_events, children.handles, children.num_children * sizeof(HANDLE)); memcpy(all_events, children.handles, live_children * sizeof(HANDLE));
memcpy(all_events + children.num_children, events, num_events * sizeof(HANDLE)); memcpy(all_events + live_children, events, num_events * sizeof(HANDLE));
/* TODO - implement signal catching and handling */ /* TODO - implement signal catching and handling */
if (num_all_events) { if (num_all_events) {
@ -507,11 +259,8 @@ 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)) { if ((ret >= WAIT_OBJECT_0) && (ret <= WAIT_OBJECT_0 + num_all_events - 1)) {
//woken up by event signalled //woken up by event signalled
/* is this due to a child process going down*/ /* is this due to a child process going down*/
if (children.num_children && ((ret - WAIT_OBJECT_0) < children.num_children)) { if (children.num_children && ((ret - WAIT_OBJECT_0) < children.num_children))
sigaddset(&pending_signals, W32_SIGCHLD); sigaddset(&pending_signals, W32_SIGCHLD);
//errno = EINTR;
//return -1;
}
} }
else if (ret == WAIT_IO_COMPLETION) { else if (ret == WAIT_IO_COMPLETION) {
/* APC processed due to IO or signal*/ /* APC processed due to IO or signal*/

View File

@ -0,0 +1,35 @@
#include <Windows.h>
#include "inc\defs.h"
int sw_initialize();
sighandler_t sw_signal(int signum, sighandler_t handler);
int sw_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
int sw_raise(int sig);
int sw_kill(int pid, int sig);
/* child processes */
#define MAX_CHILDREN 50
struct _children {
HANDLE handles[MAX_CHILDREN];
DWORD process_id[MAX_CHILDREN];
/* total children */
DWORD num_children;
/* #zombies */
/* (num_chileren - zombies) are live children */
DWORD num_zombies;
};
int sw_add_child(HANDLE child, DWORD pid);
int sw_remove_child_at_index(DWORD index);
int sw_child_to_zombie(DWORD index);
int sw_remove_child(HANDLE child);
void sw_cleanup_child_zombies();
struct _timer_info {
HANDLE timer;
ULONGLONG ticks_at_start; /* 0 if timer is not live */
__int64 run_time_sec; /* time in seconds, timer is set to go off from ticks_at_start */
};
int sw_init_timer();
unsigned int sw_alarm(unsigned int seconds);

View File

@ -0,0 +1,88 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Copyright(c) 2015 Microsoft Corp.
* All rights reserved
*
* Helper routines to support SIGALRM
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "signal_internal.h"
struct _timer_info timer_info;
extern sigset_t pending_signals;
static VOID CALLBACK
sigalrm_APC(
_In_opt_ LPVOID lpArgToCompletionRoutine,
_In_ DWORD dwTimerLowValue,
_In_ DWORD dwTimerHighValue
) {
sigaddset(&pending_signals, W32_SIGALRM);
}
unsigned int
sw_alarm(unsigned int sec) {
LARGE_INTEGER due;
ULONGLONG sec_passed;
int ret = 0;
errno = 0;
/* cancel any live timer if seconds is 0*/
if (sec == 0) {
CancelWaitableTimer(timer_info.timer);
timer_info.ticks_at_start = 0;
timer_info.run_time_sec = 0;
return 0;
}
due.QuadPart = -10000000LL; //1 sec in 100 nanosec intervals
due.QuadPart *= sec;
/* this call resets the timer if it is already active */
if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) {
debug("alram() - ERROR SetWaitableTimer() %d", GetLastError());
return 0;;
}
/* if timer was already ative, return when it was due */
if (timer_info.ticks_at_start) {
sec_passed = (GetTickCount64() - timer_info.ticks_at_start) / 1000;
if (sec_passed < timer_info.run_time_sec)
ret = timer_info.run_time_sec - sec_passed;
}
timer_info.ticks_at_start = GetTickCount64();
timer_info.run_time_sec = sec;
return ret;
}
int
sw_init_timer() {
memset(&timer_info, 0, sizeof(timer_info));
timer_info.timer = CreateWaitableTimer(NULL, TRUE, NULL);
if (timer_info.timer == NULL) {
errno = ENOMEM;
return -1;
}
return 0;
}

View File

@ -0,0 +1,228 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Copyright(c) 2015 Microsoft Corp.
* All rights reserved
*
* Helper routines to support SIGCLD and related routines implementation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "signal_internal.h"
struct _children children;
int
sw_add_child(HANDLE child, DWORD pid) {
DWORD first_zombie_index;
debug("Register child %p pid %d, %d zombies of %d", child, pid,
children.num_zombies, children.num_children);
if (children.num_children == MAX_CHILDREN) {
errno = ENOMEM;
return -1;
}
if (children.num_zombies) {
first_zombie_index = children.num_children - children.num_zombies;
children.handles[children.num_children] = children.handles[first_zombie_index];
children.process_id[children.num_children] = children.process_id[first_zombie_index];
children.handles[first_zombie_index] = child;
children.process_id[first_zombie_index] = pid;
}
else {
children.handles[children.num_children] = child;
children.process_id[children.num_children] = pid;
}
children.num_children++;
return 0;
}
int
sw_remove_child_at_index(DWORD index) {
DWORD last_non_zombie;
debug("Unregister child at index %d, %d zombies of %d", index,
children.num_zombies, children.num_children);
if ((index >= children.num_children)
|| (children.num_children == 0)) {
errno = EINVAL;
return -1;
}
CloseHandle(children.handles[index]);
if (children.num_zombies == 0) {
children.handles[index] = children.handles[children.num_children - 1];
children.process_id[index] = children.process_id[children.num_children - 1];
}
else {
/* if its a zombie */
if (index >= (children.num_children - children.num_zombies)) {
children.handles[index] = children.handles[children.num_children - 1];
children.process_id[index] = children.process_id[children.num_children - 1];
children.num_zombies--;
}
else {
last_non_zombie = children.num_children - children.num_zombies - 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[children.num_children - 1];
children.process_id[last_non_zombie] = children.process_id[children.num_children - 1];
}
}
children.num_children--;
return 0;
}
int
sw_child_to_zombie(DWORD index) {
DWORD last_non_zombie, last_child, zombie_pid;
HANDLE zombie_handle;
debug("zombie'ing child at index %d, %d zombies of %d", index,
children.num_zombies, children.num_children);
if (index >= children.num_children) {
errno = EINVAL;
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];
children.num_zombies++;
return 0;
}
int
sw_remove_child(HANDLE child) {
HANDLE* handles = children.handles;
DWORD num_children = children.num_children;
while (num_children) {
if (*handles == child)
return sw_remove_child_at_index(children.num_children - num_children);
handles++;
num_children--;
}
errno = EINVAL;
return -1;
}
int waitpid(int pid, int *status, int options) {
DWORD index, ret, ret_id, exit_code, timeout = 0;
HANDLE process = NULL;
if (options & (~WNOHANG)) {
errno = ENOTSUP;
DebugBreak();
return -1;
}
if ((pid < -1) || (pid == 0)) {
errno = ENOTSUP;
DebugBreak();
return -1;
}
if (children.num_children == 0) {
errno = ECHILD;
return -1;
}
if (pid > 0) {
if (options != 0) {
errno = ENOTSUP;
DebugBreak();
return -1;
}
/* find entry in table */
for (index = 0; index < children.num_children; index++)
if (children.process_id[index] == pid)
break;
if (index == children.num_children) {
errno = ECHILD;
return -1;
}
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);
CloseHandle(process);
sw_remove_child_at_index(index);
if (status)
*status = exit_code;
return ret_id;
}
/* pid = -1*/
timeout = INFINITE;
if (options & WNOHANG)
timeout = 0;
ret = WaitForMultipleObjects(children.num_children, children.handles, FALSE, timeout);
if ((ret >= WAIT_OBJECT_0) && (ret < (WAIT_OBJECT_0 + children.num_children))) {
index = ret - WAIT_OBJECT_0;
process = children.handles[index];
ret_id = children.process_id[index];
GetExitCodeProcess(process, &exit_code);
CloseHandle(process);
sw_remove_child_at_index(index);
if (status)
*status = exit_code;
return ret_id;
}
else if (ret == WAIT_TIMEOUT) {
/* TODO - assert that WNOHANG was specified*/
return 0;
}
DebugBreak();//fatal
return -1;
}
void
sw_cleanup_child_zombies() {
int pid = 1;
while (pid > 0) {
pid = waitpid(-1, NULL, WNOHANG);
}
}

View File

@ -121,16 +121,6 @@ FILE* fileio_fdopen(struct w32_io* pio, const char *mode);
/* terminal io specific versions */ /* terminal io specific versions */
int termio_close(struct w32_io* pio); int termio_close(struct w32_io* pio);
/* signal related APIs*/
int sw_initialize();
int sw_add_child(HANDLE child, DWORD pid);
int sw_remove_child(HANDLE child);
unsigned int sw_alarm(unsigned int seconds);
sighandler_t sw_signal(int signum, sighandler_t handler);
int sw_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
int sw_raise(int sig);
int sw_kill(int pid, int sig);
/* /*
* open() flags and modes * open() flags and modes
* all commented out macros are defined in fcntl.h * all commented out macros are defined in fcntl.h