diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index 8f4183c..d6756c9 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -495,9 +495,6 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) { &pio->write_overlapped, &WriteCompletionRoutine)) { pio->write_details.pending = TRUE; pio->write_details.remaining = bytes_copied; - /* execute APC if write has completed */ - if (wait_for_any_event(NULL, 0, 0) == -1) - return -1; } else { errno = errno_from_Win32LastError(); @@ -513,10 +510,23 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) { if (w32_io_is_blocking(pio)) { while (pio->write_details.pending) { - if (wait_for_any_event(NULL, 0, INFINITE) == -1) - return -1; + if (wait_for_any_event(NULL, 0, INFINITE) == -1) { + /* if interrupted but write has completed, we are good*/ + if ((errno != EINTR) || (pio->write_details.pending)) + return -1; + errno = 0; + } } } + /* execute APC to give a chance for write to complete */ + else if (wait_for_any_event(NULL, 0, 0) == -1) { + /* if interrupted but write has completed, we are good*/ + if ((errno != EINTR) || (pio->write_details.pending)) + return -1; + errno = 0; + } + + /* if write has completed, pick up any error reported*/ if (!pio->write_details.pending && pio->write_details.error) { errno = errno_from_Win32Error(pio->write_details.error); debug("write - ERROR from cb:%d, io:%p", pio->write_details.error, pio); diff --git a/contrib/win32/win32compat/inc/defs.h b/contrib/win32/win32compat/inc/defs.h index 3e8b604..38c1316 100644 --- a/contrib/win32/win32compat/inc/defs.h +++ b/contrib/win32/win32compat/inc/defs.h @@ -51,12 +51,6 @@ #define W32_SIGMAX 12 -/* signal action codes*/ -#define W32_SIG_ERR -1 -#define W32_SIG_DFL 0 -#define W32_SIG_IGN 1 -#define W32_SIG_USR 2 - /* singprocmask "how" codes*/ #define SIG_BLOCK 0 #define SIG_UNBLOCK 1 @@ -69,6 +63,10 @@ typedef int sigset_t; #define sigismember(set, sig) ( (*(set) & (0x80000000 >> (sig)))?1:0 ) #define sigdelset(set, sig) ( (*(set)) &= (~( 0x80000000 >> (sig)) ) ) +/* signal action codes*/ +#define W32_SIG_ERR ((sighandler_t)-1) +#define W32_SIG_DFL ((sighandler_t)0) +#define W32_SIG_IGN ((sighandler_t)1) typedef unsigned short _mode_t; typedef _mode_t mode_t; diff --git a/contrib/win32/win32compat/inc/dlfcn.h b/contrib/win32/win32compat/inc/dlfcn.h index e7201d7..6536041 100644 --- a/contrib/win32/win32compat/inc/dlfcn.h +++ b/contrib/win32/win32compat/inc/dlfcn.h @@ -4,8 +4,8 @@ #define dlerror() GetLastError() -HMODULE *dlopen(const char *filename, int flags); +HMODULE dlopen(const char *filename, int flags); -int dlclose(HMODULE *handle); +int dlclose(HMODULE handle); -FARPROC *dlsym(HMODULE *handle, const char *symbol); \ No newline at end of file +FARPROC dlsym(HMODULE handle, const char *symbol); \ No newline at end of file diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index 9e9cbfd..666b4aa 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -63,14 +63,15 @@ int fstatvfs(int fd, struct statvfs *buf) { } #include "inc\dlfcn.h" -HMODULE *dlopen(const char *filename, int flags) { +HMODULE dlopen(const char *filename, int flags) { return LoadLibraryA(filename); } -int dlclose(HMODULE *handle) { +int dlclose(HMODULE handle) { FreeLibrary(handle); + return 0; } -FARPROC *dlsym(HMODULE *handle, const char *symbol) { +FARPROC dlsym(HMODULE handle, const char *symbol) { return GetProcAddress(handle, symbol); } \ No newline at end of file diff --git a/contrib/win32/win32compat/signal.c b/contrib/win32/win32compat/signal.c index 438626c..827adff 100644 --- a/contrib/win32/win32compat/signal.c +++ b/contrib/win32/win32compat/signal.c @@ -33,16 +33,11 @@ #include #include "inc\defs.h" -/* pending signals to be processed s*/ +/* pending signals to be processed */ sigset_t pending_signals; /* signal handler table*/ -struct { - sighandler_t handler; - sighandler_t default_handler; - DWORD disposition; - -} signal_info[W32_SIGMAX]; +sighandler_t sig_handlers[W32_SIGMAX]; static VOID CALLBACK sigint_APCProc( @@ -56,7 +51,7 @@ native_sig_handler(int signal) { if (signal == SIGINT) { /* Queue signint APC */ - QueueUserAPC(sigint_APCProc, main_thread, NULL); + QueueUserAPC(sigint_APCProc, main_thread, (ULONG_PTR)NULL); } } @@ -67,11 +62,8 @@ sw_init_signal_handler_table() { /* TODO SetConsoleCtrlHandler */ //signal(SIGINT, native_sig_handler); sigemptyset(&pending_signals); - memset(&signal_info, 0, sizeof(signal_info)); - for (i = 0; i < W32_SIGMAX; i++) { - - } - + /* this automatically sets all to SIG_DFL (0)*/ + memset(sig_handlers, 0, sizeof(sig_handlers)); } /* child processes */ @@ -142,25 +134,26 @@ sigalrm_APC( } unsigned int -sw_alarm(unsigned int seconds) { +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 (seconds == 0) { + if (sec == 0) { CancelWaitableTimer(timer_info.timer); timer_info.ticks_at_start = 0; timer_info.run_time_sec = 0; return 0; } - due.QuadPart = (-1) * seconds * 1000 * 1000 *10; //100 nanosec intervals + 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)) { - errno = EOTHER; - return -1; + debug("alram() - ERROR SetWaitableTimer() %d", GetLastError()); + return 0;; } /* if timer was already ative, return when it was due */ @@ -170,14 +163,14 @@ sw_alarm(unsigned int seconds) { ret = timer_info.run_time_sec - sec_passed; } timer_info.ticks_at_start = GetTickCount64(); - timer_info.run_time_sec = seconds; + 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, FALSE, NULL); + timer_info.timer = CreateWaitableTimer(NULL, TRUE, NULL); if (timer_info.timer == NULL) { errno = ENOMEM; return -1; @@ -190,43 +183,54 @@ sw_signal(int signum, sighandler_t handler) { sighandler_t prev; if (signum >= W32_SIGMAX) { errno = EINVAL; - return SIG_ERR; + return W32_SIG_ERR; } - prev = signal_info[signum].disposition; - if (prev == W32_SIG_USR) - prev = signal_info[signum].handler; - - /* standard dispositions */ - if ((handler == W32_SIG_DFL) || (handler == W32_SIG_DFL)) { - signal_info[signum].disposition = handler; - signal_info[signum].handler = NULL; - } - else { /* user defined handler*/ - signal_info[signum].disposition = W32_SIG_USR; - signal_info[signum].handler = handler; - } + prev = sig_handlers[signum]; + sig_handlers[signum] = handler; return prev; } int sw_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) { /* this is only used by sshd to block SIGCHLD while doing waitpid() */ - /* our implementation of waidpid() is never interrupted, so no need to implement this*/ + /* our implementation of waidpid() is never interrupted, so no need to implement this for now*/ return 0; } + + int sw_raise(int sig) { if (sig == W32_SIGSEGV) raise(SIGSEGV); /* raise native exception handler*/ - - if (signal_info[sig].disposition == W32_SIG_IGN) + + if (sig >= W32_SIGMAX) { + errno = EINVAL; + return -1; + } + + /* execute user specified disposition */ + if (sig_handlers[sig] > W32_SIG_IGN) { + sig_handlers[sig](sig); return 0; - else if (signal_info[sig].disposition == W32_SIG_DFL) - signal_info[sig].default_handler(sig); - else - signal_info[sig].handler(sig); + } + + /* if set to ignore, nothing to do */ + if (sig_handlers[sig] == W32_SIG_IGN) + return 0; + + /* execute any default handlers */ + switch (sig) { + case W32_SIGCHLD: + /*TODO - execute sigchild default handler */ + break; + case W32_SIGINT: + /* TODO - execute sigint default handler */ + break; + default: + break; + } return 0; } @@ -237,7 +241,7 @@ sw_kill(int pid, int sig) { if (pid == GetCurrentProcessId()) return sw_raise(sig); - /* only SIGTERM supported for child processes*/ + /* for child processes - only SIGTERM supported*/ /* TODO implement kill(SIGTERM) for child processes */ return 0; } @@ -254,7 +258,6 @@ sw_process_pending_signals() { /* check for expected signals*/ for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++) sigdelset(&pending_tmp, exp[i]); - if (pending_tmp) { /* unexpected signals queued up */ errno = ENOTSUP; @@ -262,17 +265,34 @@ sw_process_pending_signals() { return -1; } + /* take pending_signals local to prevent recursion in wait_for_any* loop */ + pending_tmp = pending_signals; + pending_signals = 0; for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++) { - if (signal_info[exp[i]].disposition != W32_SIG_IGN) { - raise(exp[i]); - sig_int = TRUE; + if (sigismember(&pending_tmp, exp[i])) { + if (sig_handlers[exp[i]] != W32_SIG_IGN) { + sw_raise(exp[i]); + sig_int = TRUE; + } + else {/* disposition is W32_SIG_IGN */ + /* TODO for SIG_CHLD - do clean up of Zombies */ + } + + sigdelset(&pending_tmp, exp[i]); } } + + /* by now all pending signals should have been taken care of*/ + if (pending_tmp) + DebugBreak(); + if (sig_int) { - /* processed a signal that was not set to be ignored */ - errno = SIGINT; - return -1; + /* processed a signal that was set not to be ignored */ + debug("process_queued_signals: WARNING - A signal has interrupted and was processed"); + /* there are parts of code that do not tolerate EINT during IO, so returning 0 here*/ + //errno = EINTR; + //return -1; } return 0; @@ -315,8 +335,8 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds) //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)) { - //sigaddset(&pending_signals, W32_SIGCHLD); /* TODO - enable this once all direct closes are removed in core code*/ + //sigaddset(&pending_signals, W32_SIGCHLD); //sw_remove_child(ret - WAIT_OBJECT_0); errno = EINTR; return -1; @@ -352,10 +372,9 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds) } } - - /*if (pending_signals) { + if (pending_signals) { return sw_process_pending_signals(); - }*/ + } return 0; } diff --git a/contrib/win32/win32compat/socketio.c b/contrib/win32/win32compat/socketio.c index 28ddecd..27b4c03 100644 --- a/contrib/win32/win32compat/socketio.c +++ b/contrib/win32/win32compat/socketio.c @@ -578,7 +578,7 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) { wsabuf.len = min(wsabuf.len, (int)len); memcpy(wsabuf.buf, buf, wsabuf.len); - /* implement flags support if needed */ + /* TODO - implement flags support if needed */ ret = WSASend(pio->sock, &wsabuf, 1, NULL, 0, &pio->write_overlapped, &WSASendCompletionRoutine); @@ -588,8 +588,13 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) { debug2("send - WSASend() returned 0, APC scheduled io:%p", pio); pio->write_details.pending = TRUE; pio->write_details.remaining = wsabuf.len; - if (wait_for_any_event(NULL, 0, 0) == -1) - return -1; + if (wait_for_any_event(NULL, 0, 0) == -1) { + //interrupted but send went through + if (errno == EINTR) + errno = 0; + else + return -1; + } if ((pio->write_details.pending) || (pio->write_details.remaining != 0)) { errno = EOTHER; debug("send - ERROR: Unexpected IO state, io:%p", pio); @@ -611,8 +616,12 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) { /* wait until io is done */ debug3("send - waiting as socket is in blocking mode, io:%p", pio); while (pio->write_details.pending) - if (wait_for_any_event(NULL, 0,INFINITE) == -1) - return -1; + if (wait_for_any_event(NULL, 0, INFINITE) == -1) { + /* if interrupted but send has completed, we are good*/ + if ((errno != EINTR) || (pio->write_details.pending)) + return -1; + errno = 0; + } } debug3("send - returning %d, io:%p", wsabuf.len, pio); diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c index 7963346..da5d813 100644 --- a/contrib/win32/win32compat/w32fd.c +++ b/contrib/win32/win32compat/w32fd.c @@ -779,7 +779,7 @@ int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock) { unsigned int w32_alarm(unsigned int seconds) { - return 0; + return sw_alarm(seconds);; } sighandler_t w32_signal(int signum, sighandler_t handler) {