mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-24 14:35:35 +02:00
Fixes in signal handler and working SFTP progress bar (enabled using alarm())
This commit is contained in:
parent
eed9299081
commit
a3cc5c797d
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
FARPROC dlsym(HMODULE handle, const char *symbol);
|
@ -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);
|
||||
}
|
@ -33,16 +33,11 @@
|
||||
#include <signal.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user