diff --git a/contrib/win32/win32compat/inc/w32posix.h b/contrib/win32/win32compat/inc/w32posix.h index 2612e11..5f6f3ce 100644 --- a/contrib/win32/win32compat/inc/w32posix.h +++ b/contrib/win32/win32compat/inc/w32posix.h @@ -103,12 +103,13 @@ typedef void(*sighandler_t)(int); /* * these routines are temporarily defined here to allow transition * from older POSIX wrapper to the newer one. After complete transition - * these should move to a internal header. + * these should be gone or moved to a internal header. */ int w32_temp_DelChildToWatch(HANDLE processtowatch); int w32_temp_AddChildToWatch(HANDLE processtowatch); HANDLE w32_fd_to_handle(int fd); int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock); +int signalio_add_child(HANDLE child); /* temporary definitions to aid in transition */ #define WSHELPDelChildToWatch(a) w32_temp_DelChildToWatch((a)) diff --git a/contrib/win32/win32compat/signal.c b/contrib/win32/win32compat/signal.c index f2531ea..e662d45 100644 --- a/contrib/win32/win32compat/signal.c +++ b/contrib/win32/win32compat/signal.c @@ -35,6 +35,62 @@ /* signal queue */ +/* child processes */ +#define MAX_CHILDREN 50 +struct _children { + HANDLE handles[MAX_CHILDREN]; + DWORD num_children; +} children; + +void +signalio_initialize() { + memset(&children, 0, sizeof(children)); +} + +int +signalio_add_child(HANDLE child) { + if (children.num_children == MAX_CHILDREN) { + errno = ENOTSUP; + return -1; + } + children.handles[children.num_children++] = child; + return 0; +} + +int +signalio_remove_child_at_index(DWORD index) { + if (index >= children.num_children) { + errno = EINVAL; + return -1; + } + + CloseHandle(children.handles[index]); + if ((children.num_children > 1) && (index != (children.num_children - 1))) { + children.handles[index] = children.handles[children.num_children - 1]; + } + + children.num_children--; + return 0; +} + + +int +signalio_remove_child(HANDLE child) { + HANDLE* handles = children.handles; + DWORD num_children = children.num_children; + + while (num_children) { + if (*handles == child) + return signalio_remove_child_at_index(children.num_children - num_children); + handles++; + num_children--; + } + + errno = EINVAL; + return -1; +} + + /* * Main wait routine used by all blocking calls. * It wakes up on @@ -49,12 +105,31 @@ int wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds) { + HANDLE all_events[MAXIMUM_WAIT_OBJECTS]; + DWORD num_all_events = num_events + children.num_children; + + if (num_all_events > MAXIMUM_WAIT_OBJECTS) { + errno = ENOTSUP; + return -1; + } + + memcpy(all_events, children.handles, children.num_children * sizeof(HANDLE)); + memcpy(all_events + children.num_children, events, num_events * sizeof(HANDLE)); + /* TODO - implement signal catching and handling */ - if (num_events) { - DWORD ret = WaitForMultipleObjectsEx(num_events, events, FALSE, + if (num_all_events) { + DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE, milli_seconds, TRUE); - if ((ret >= WAIT_OBJECT_0) && (ret <= WAIT_OBJECT_0 + num_events - 1)) { + 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)) { + /* TODO - enable this once all direct closes are removed in core code*/ + //signalio_remove_child(ret - WAIT_OBJECT_0); + errno = EINTR; + return -1; + } + return 0; } else if (ret == WAIT_IO_COMPLETION) { diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index b50e36f..4823849 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -120,6 +120,7 @@ w32posix_initialize() { if ((fd_table_initialize() != 0) || (socketio_initialize() != 0)) DebugBreak(); + signalio_initialize(); } void diff --git a/contrib/win32/win32compat/w32fd.h b/contrib/win32/win32compat/w32fd.h index 07f09b2..2ddce2d 100644 --- a/contrib/win32/win32compat/w32fd.h +++ b/contrib/win32/win32compat/w32fd.h @@ -121,7 +121,10 @@ long fileio_lseek(struct w32_io* pio, long offset, int origin); int fileio_isatty(struct w32_io* pio); FILE* fileio_fdopen(struct w32_io* pio, const char *mode); - +/* signal related APIs*/ +void signalio_initialize(); +//int signalio_add_child(HANDLE child); +//int signalio_remove_child(HANDLE child); /* * open() flags and modes diff --git a/serverloop.c b/serverloop.c index 2d92317..321e868 100644 --- a/serverloop.c +++ b/serverloop.c @@ -882,11 +882,8 @@ collect_children(void) session_close_by_pid(s->pid, status); - if (s->pid) - CloseHandle(process); - /*TODO - fix this*/ - //int WSHELPDelChildToWatch (HANDLE processtowatch); - //WSHELPDelChildToWatch (process); // take the process off from watch list in select mux + signalio_remove_child(process); + } } } while (i > 0); diff --git a/session.c b/session.c index e2fce2b..b18eb35 100644 --- a/session.c +++ b/session.c @@ -920,6 +920,7 @@ do_exec_no_pty(Session *s, const char *command) s -> pid = pi.hProcess; s -> processId = pi.dwProcessId; + signalio_add_child(pi.hProcess); // Add the child process created to select mux so that during our select data call we know if the process has exited /* TODO - fix thi s*/ @@ -939,7 +940,7 @@ do_exec_no_pty(Session *s, const char *command) close(pipein[0]); close(pipeout[1]); - close(pipeout[1]); + close(pipeerr[1]); ResumeThread ( pi.hThread ); /* now let cmd shell main thread be active s we have closed all i/o file handle that cmd will use */ SetConsoleCtrlHandler(NULL, TRUE);