Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated Signal Handler #287

Merged
merged 3 commits into from
Mar 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 23 additions & 40 deletions contrib/win32/win32compat/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,59 +260,42 @@ sw_process_pending_signals()
int
wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
{
HANDLE all_events[MAXIMUM_WAIT_OBJECTS];
DWORD num_all_events;
HANDLE all_events[MAXIMUM_WAIT_OBJECTS_ENHANCED];
DWORD live_children = children.num_children - children.num_zombies;
DWORD num_all_events = num_events + live_children;
errno_t r = 0;

num_all_events = num_events + live_children;

if (num_all_events > MAXIMUM_WAIT_OBJECTS) {
debug3("wait() - ERROR max events reached");
if (num_all_events > MAXIMUM_WAIT_OBJECTS_ENHANCED) {
debug3("wait_for_any_event() - ERROR max events reached");
errno = ENOTSUP;
return -1;
}

if ((r = memcpy_s(all_events, MAXIMUM_WAIT_OBJECTS * sizeof(HANDLE), children.handles, live_children * sizeof(HANDLE)) != 0) ||
( r = memcpy_s(all_events + live_children, (MAXIMUM_WAIT_OBJECTS - live_children) * sizeof(HANDLE), events, num_events * sizeof(HANDLE)) != 0)) {
if ((r = memcpy_s(all_events, MAXIMUM_WAIT_OBJECTS_ENHANCED * sizeof(HANDLE), children.handles, live_children * sizeof(HANDLE)) != 0) ||
( r = memcpy_s(all_events + live_children, (MAXIMUM_WAIT_OBJECTS_ENHANCED - live_children) * sizeof(HANDLE), events, num_events * sizeof(HANDLE)) != 0)) {
debug3("memcpy_s failed with error: %d.", r);
return -1;
}

debug5("wait() on %d events and %d children", num_events, live_children);
/* TODO - implement signal catching and handling */
if (num_all_events) {
DWORD ret = wait_for_multiple_objects_enhanced(num_all_events, all_events, milli_seconds, TRUE);
if ((ret >= WAIT_OBJECT_0_ENHANCED) && (ret <= WAIT_OBJECT_0_ENHANCED + num_all_events - 1)) {
/* woken up by event signalled
* is this due to a child process going down
*/
if (live_children && ((ret - WAIT_OBJECT_0_ENHANCED) < live_children)) {
sigaddset(&pending_signals, W32_SIGCHLD);
sw_child_to_zombie(ret - WAIT_OBJECT_0_ENHANCED);
}
} else if (ret == WAIT_IO_COMPLETION_ENHANCED) {
/* APC processed due to IO or signal*/
} else if (ret == WAIT_TIMEOUT_ENHANCED) {
/* timed out */
return 0;
} else { /* some other error*/
errno = EOTHER;
debug3("ERROR: unxpected wait end: %d", ret);
return -1;
}
} else {
DWORD ret = SleepEx(milli_seconds, TRUE);
if (ret == WAIT_IO_COMPLETION) {
/* APC processed due to IO or signal*/
} else if (ret == 0) {
/* timed out */
return 0;
} else { /* some other error */
errno = EOTHER;
debug3("ERROR: unxpected SleepEx error: %d", ret);
return -1;
DWORD ret = wait_for_multiple_objects_enhanced(num_all_events, all_events, milli_seconds, TRUE);
if ((ret >= WAIT_OBJECT_0_ENHANCED) && (ret <= WAIT_OBJECT_0_ENHANCED + num_all_events - 1)) {
/* woken up by event signaled
* is this due to a child process going down
*/
if (live_children && ((ret - WAIT_OBJECT_0_ENHANCED) < live_children)) {
sigaddset(&pending_signals, W32_SIGCHLD);
sw_child_to_zombie(ret - WAIT_OBJECT_0_ENHANCED);
}
} else if (ret == WAIT_IO_COMPLETION_ENHANCED) {
/* APC processed due to IO or signal*/
} else if (ret == WAIT_TIMEOUT_ENHANCED) {
/* timed out */
return 0;
} else { /* some other error*/
errno = EOTHER;
debug3("ERROR: unexpected wait end: %d", ret);
return -1;
}

if (pending_signals)
Expand Down
5 changes: 3 additions & 2 deletions contrib/win32/win32compat/signal_internal.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#include <Windows.h>

/* child processes */
#define MAX_CHILDREN 500
#define MAX_CHILDREN 512

struct _children {
/*
* array of handles and process_ids.
* intial (num_children - num_zombies) are alive
* initial (num_children - num_zombies) are alive
* rest are zombies
*/
HANDLE handles[MAX_CHILDREN];
Expand All @@ -32,6 +32,7 @@ struct _timer_info {
};
int sw_init_timer();

#define MAXIMUM_WAIT_OBJECTS_ENHANCED 1024
#define WAIT_OBJECT_0_ENHANCED 0x00000000
#define WAIT_ABANDONED_0_ENHANCED 0x10000000
#define WAIT_TIMEOUT_ENHANCED 0x20000000
Expand Down
34 changes: 21 additions & 13 deletions contrib/win32/win32compat/signal_wait.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,34 @@ DWORD
wait_for_multiple_objects_enhanced(_In_ DWORD nCount, _In_ const HANDLE *lpHandles,
_In_ DWORD dwMilliseconds, _In_ BOOL bAlertable)
{

/* number of separate bins / threads required to monitor execution */
const DWORD bin_size = MAXIMUM_WAIT_OBJECTS;
const DWORD bins_total = (nCount - 1) / bin_size + 1;

DWORD return_value = WAIT_FAILED_ENHANCED;
HANDLE wait_event = NULL;
wait_for_multiple_objects_struct *wait_bins = NULL;
wait_for_multiple_objects_struct wait_bins[(MAXIMUM_WAIT_OBJECTS_ENHANCED - 1) / MAXIMUM_WAIT_OBJECTS + 1] = { 0 };
DWORD wait_ret;

/* protect against too many events */
if (nCount > MAXIMUM_WAIT_OBJECTS_ENHANCED)
{
return WAIT_FAILED_ENHANCED;
}

/* in the event that no events are passed and alterable, just do a sleep and
* and wait for wakeup call. This differs from the WaitForMultipleObjectsEx
* call which would return an error if no events are passed to the function. */
if (nCount == 0 && bAlertable)
{
DWORD wait_ret = SleepEx(dwMilliseconds, TRUE);
if (wait_ret == 0)
return WAIT_TIMEOUT_ENHANCED;
else if (wait_ret == WAIT_IO_COMPLETION)
return WAIT_IO_COMPLETION_ENHANCED;
else
return WAIT_FAILED_ENHANCED;
}

/* if less than the normal maximum then just use the built-in function
* to avoid the overhead of another thread */
Expand All @@ -108,21 +127,12 @@ wait_for_multiple_objects_enhanced(_In_ DWORD nCount, _In_ const HANDLE *lpHand
return WAIT_FAILED_ENHANCED;
}


/* setup synchronization event to flag when the main thread should wake up */
wait_event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (wait_event == NULL) {
goto cleanup;
}

/* allocate an area to communicate with our threads */
wait_bins = (wait_for_multiple_objects_struct *)
calloc(bins_total, sizeof(wait_for_multiple_objects_struct));
if (wait_bins == NULL) {
goto cleanup;
}

ZeroMemory(wait_bins, bins_total * sizeof(wait_for_multiple_objects_struct));
/* initialize each thread that handles up to MAXIMUM_WAIT_OBJECTS each */
for (DWORD bin = 0; bin < bins_total; bin++) {

Expand Down Expand Up @@ -220,7 +230,5 @@ wait_for_multiple_objects_enhanced(_In_ DWORD nCount, _In_ const HANDLE *lpHand

if (wait_event)
CloseHandle(wait_event);
if (wait_bins)
free(wait_bins);
return return_value;
}
2 changes: 1 addition & 1 deletion contrib/win32/win32compat/w32fd.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ w32_fcntl(int fd, int cmd, ... /* arg */)
return ret;
}

#define SELECT_EVENT_LIMIT 32
#define SELECT_EVENT_LIMIT 512
int
w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* exceptfds, const struct timeval *timeout)
{
Expand Down