Fixes in signal handler and working SFTP progress bar (enabled using alarm())

This commit is contained in:
Manoj Ampalam 2016-03-24 14:16:36 -07:00
parent eed9299081
commit a3cc5c797d
7 changed files with 113 additions and 76 deletions

View File

@ -495,9 +495,6 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
&pio->write_overlapped, &WriteCompletionRoutine)) { &pio->write_overlapped, &WriteCompletionRoutine)) {
pio->write_details.pending = TRUE; pio->write_details.pending = TRUE;
pio->write_details.remaining = bytes_copied; pio->write_details.remaining = bytes_copied;
/* execute APC if write has completed */
if (wait_for_any_event(NULL, 0, 0) == -1)
return -1;
} }
else { else {
errno = errno_from_Win32LastError(); 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)) { if (w32_io_is_blocking(pio)) {
while (pio->write_details.pending) { while (pio->write_details.pending) {
if (wait_for_any_event(NULL, 0, INFINITE) == -1) if (wait_for_any_event(NULL, 0, INFINITE) == -1) {
return -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) { if (!pio->write_details.pending && pio->write_details.error) {
errno = errno_from_Win32Error(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); debug("write - ERROR from cb:%d, io:%p", pio->write_details.error, pio);

View File

@ -51,12 +51,6 @@
#define W32_SIGMAX 12 #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*/ /* singprocmask "how" codes*/
#define SIG_BLOCK 0 #define SIG_BLOCK 0
#define SIG_UNBLOCK 1 #define SIG_UNBLOCK 1
@ -69,6 +63,10 @@ typedef int sigset_t;
#define sigismember(set, sig) ( (*(set) & (0x80000000 >> (sig)))?1:0 ) #define sigismember(set, sig) ( (*(set) & (0x80000000 >> (sig)))?1:0 )
#define sigdelset(set, sig) ( (*(set)) &= (~( 0x80000000 >> (sig)) ) ) #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 unsigned short _mode_t;
typedef _mode_t mode_t; typedef _mode_t mode_t;

View File

@ -4,8 +4,8 @@
#define dlerror() GetLastError() #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); FARPROC dlsym(HMODULE handle, const char *symbol);

View File

@ -63,14 +63,15 @@ int fstatvfs(int fd, struct statvfs *buf) {
} }
#include "inc\dlfcn.h" #include "inc\dlfcn.h"
HMODULE *dlopen(const char *filename, int flags) { HMODULE dlopen(const char *filename, int flags) {
return LoadLibraryA(filename); return LoadLibraryA(filename);
} }
int dlclose(HMODULE *handle) { int dlclose(HMODULE handle) {
FreeLibrary(handle); FreeLibrary(handle);
return 0;
} }
FARPROC *dlsym(HMODULE *handle, const char *symbol) { FARPROC dlsym(HMODULE handle, const char *symbol) {
return GetProcAddress(handle, symbol); return GetProcAddress(handle, symbol);
} }

View File

@ -33,16 +33,11 @@
#include <signal.h> #include <signal.h>
#include "inc\defs.h" #include "inc\defs.h"
/* pending signals to be processed s*/ /* pending signals to be processed */
sigset_t pending_signals; sigset_t pending_signals;
/* signal handler table*/ /* signal handler table*/
struct { sighandler_t sig_handlers[W32_SIGMAX];
sighandler_t handler;
sighandler_t default_handler;
DWORD disposition;
} signal_info[W32_SIGMAX];
static VOID CALLBACK static VOID CALLBACK
sigint_APCProc( sigint_APCProc(
@ -56,7 +51,7 @@ native_sig_handler(int signal)
{ {
if (signal == SIGINT) { if (signal == SIGINT) {
/* Queue signint APC */ /* 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 */ /* TODO SetConsoleCtrlHandler */
//signal(SIGINT, native_sig_handler); //signal(SIGINT, native_sig_handler);
sigemptyset(&pending_signals); sigemptyset(&pending_signals);
memset(&signal_info, 0, sizeof(signal_info)); /* this automatically sets all to SIG_DFL (0)*/
for (i = 0; i < W32_SIGMAX; i++) { memset(sig_handlers, 0, sizeof(sig_handlers));
}
} }
/* child processes */ /* child processes */
@ -142,25 +134,26 @@ sigalrm_APC(
} }
unsigned int unsigned int
sw_alarm(unsigned int seconds) { sw_alarm(unsigned int sec) {
LARGE_INTEGER due; LARGE_INTEGER due;
ULONGLONG sec_passed; ULONGLONG sec_passed;
int ret = 0; int ret = 0;
errno = 0; errno = 0;
/* cancel any live timer if seconds is 0*/ /* cancel any live timer if seconds is 0*/
if (seconds == 0) { if (sec == 0) {
CancelWaitableTimer(timer_info.timer); CancelWaitableTimer(timer_info.timer);
timer_info.ticks_at_start = 0; timer_info.ticks_at_start = 0;
timer_info.run_time_sec = 0; timer_info.run_time_sec = 0;
return 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 */ /* this call resets the timer if it is already active */
if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) { if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) {
errno = EOTHER; debug("alram() - ERROR SetWaitableTimer() %d", GetLastError());
return -1; return 0;;
} }
/* if timer was already ative, return when it was due */ /* 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; ret = timer_info.run_time_sec - sec_passed;
} }
timer_info.ticks_at_start = GetTickCount64(); timer_info.ticks_at_start = GetTickCount64();
timer_info.run_time_sec = seconds; timer_info.run_time_sec = sec;
return ret; return ret;
} }
static int static int
sw_init_timer() { sw_init_timer() {
memset(&timer_info, 0, sizeof(timer_info)); 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) { if (timer_info.timer == NULL) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -190,43 +183,54 @@ sw_signal(int signum, sighandler_t handler) {
sighandler_t prev; sighandler_t prev;
if (signum >= W32_SIGMAX) { if (signum >= W32_SIGMAX) {
errno = EINVAL; errno = EINVAL;
return SIG_ERR; return W32_SIG_ERR;
} }
prev = signal_info[signum].disposition; prev = sig_handlers[signum];
if (prev == W32_SIG_USR) sig_handlers[signum] = handler;
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;
}
return prev; return prev;
} }
int int
sw_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) { sw_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
/* this is only used by sshd to block SIGCHLD while doing waitpid() */ /* 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; return 0;
} }
int int
sw_raise(int sig) { sw_raise(int sig) {
if (sig == W32_SIGSEGV) if (sig == W32_SIGSEGV)
raise(SIGSEGV); /* raise native exception handler*/ 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; return 0;
else if (signal_info[sig].disposition == W32_SIG_DFL) }
signal_info[sig].default_handler(sig);
else /* if set to ignore, nothing to do */
signal_info[sig].handler(sig); 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; return 0;
} }
@ -237,7 +241,7 @@ sw_kill(int pid, int sig) {
if (pid == GetCurrentProcessId()) if (pid == GetCurrentProcessId())
return sw_raise(sig); return sw_raise(sig);
/* only SIGTERM supported for child processes*/ /* for child processes - only SIGTERM supported*/
/* TODO implement kill(SIGTERM) for child processes */ /* TODO implement kill(SIGTERM) for child processes */
return 0; return 0;
} }
@ -254,7 +258,6 @@ sw_process_pending_signals() {
/* check for expected signals*/ /* check for expected signals*/
for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++) for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++)
sigdelset(&pending_tmp, exp[i]); sigdelset(&pending_tmp, exp[i]);
if (pending_tmp) { if (pending_tmp) {
/* unexpected signals queued up */ /* unexpected signals queued up */
errno = ENOTSUP; errno = ENOTSUP;
@ -262,17 +265,34 @@ sw_process_pending_signals() {
return -1; 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++) { for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++) {
if (signal_info[exp[i]].disposition != W32_SIG_IGN) { if (sigismember(&pending_tmp, exp[i])) {
raise(exp[i]); if (sig_handlers[exp[i]] != W32_SIG_IGN) {
sig_int = TRUE; 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) { if (sig_int) {
/* processed a signal that was not set to be ignored */ /* processed a signal that was set not to be ignored */
errno = SIGINT; debug("process_queued_signals: WARNING - A signal has interrupted and was processed");
return -1; /* there are parts of code that do not tolerate EINT during IO, so returning 0 here*/
//errno = EINTR;
//return -1;
} }
return 0; return 0;
@ -315,8 +335,8 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
//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);
/* TODO - enable this once all direct closes are removed in core code*/ /* TODO - enable this once all direct closes are removed in core code*/
//sigaddset(&pending_signals, W32_SIGCHLD);
//sw_remove_child(ret - WAIT_OBJECT_0); //sw_remove_child(ret - WAIT_OBJECT_0);
errno = EINTR; errno = EINTR;
return -1; 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 sw_process_pending_signals();
}*/ }
return 0; return 0;
} }

View File

@ -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); wsabuf.len = min(wsabuf.len, (int)len);
memcpy(wsabuf.buf, buf, wsabuf.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, ret = WSASend(pio->sock, &wsabuf, 1, NULL, 0, &pio->write_overlapped,
&WSASendCompletionRoutine); &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); debug2("send - WSASend() returned 0, APC scheduled io:%p", pio);
pio->write_details.pending = TRUE; pio->write_details.pending = TRUE;
pio->write_details.remaining = wsabuf.len; pio->write_details.remaining = wsabuf.len;
if (wait_for_any_event(NULL, 0, 0) == -1) if (wait_for_any_event(NULL, 0, 0) == -1) {
return -1; //interrupted but send went through
if (errno == EINTR)
errno = 0;
else
return -1;
}
if ((pio->write_details.pending) || (pio->write_details.remaining != 0)) { if ((pio->write_details.pending) || (pio->write_details.remaining != 0)) {
errno = EOTHER; errno = EOTHER;
debug("send - ERROR: Unexpected IO state, io:%p", pio); 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 */ /* wait until io is done */
debug3("send - waiting as socket is in blocking mode, io:%p", pio); debug3("send - waiting as socket is in blocking mode, io:%p", pio);
while (pio->write_details.pending) while (pio->write_details.pending)
if (wait_for_any_event(NULL, 0,INFINITE) == -1) if (wait_for_any_event(NULL, 0, INFINITE) == -1) {
return -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); debug3("send - returning %d, io:%p", wsabuf.len, pio);

View File

@ -779,7 +779,7 @@ int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock) {
unsigned int unsigned int
w32_alarm(unsigned int seconds) { w32_alarm(unsigned int seconds) {
return 0; return sw_alarm(seconds);;
} }
sighandler_t sighandler_t
w32_signal(int signum, sighandler_t handler) { w32_signal(int signum, sighandler_t handler) {