You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/09/14 20:35:32 UTC
svn commit: r814773 - in /commons/sandbox/runtime/trunk/src/main/native:
os/win32/signals.c test/testsuite.c
Author: mturk
Date: Mon Sep 14 18:35:32 2009
New Revision: 814773
URL: http://svn.apache.org/viewvc?rev=814773&view=rev
Log:
Implement signals using completion ports
Modified:
commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c
commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c?rev=814773&r1=814772&r2=814773&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/signals.c Mon Sep 14 18:35:32 2009
@@ -47,6 +47,7 @@
#else
#define ACR_NUMSIG 33
#endif
+#define PIPE_TIMEOUT 1000
static CRITICAL_SECTION signal_lock;
int dll_daemon_mode = 0;
@@ -58,14 +59,16 @@
static volatile int signal_handlers_running;
-/* We use 4 instances as default
- * The real number should be numCPU * 2
- */
-static int sig_pipe_instances = 4;
static HANDLE sig_pipe_handle = INVALID_HANDLE_VALUE;
static wchar_t sig_pipe_name[64];
static wchar_t sig_pipe_salt[64];
+typedef struct sig_pipe_data_t {
+ OVERLAPPED ctx;
+ acr_sig_msg_t msg;
+ HANDLE pipe;
+} sig_pipe_data_t;
+
static void make_security_cookie(acr_sig_msg_t *msg, const wchar_t *salt,
DWORD sn, DWORD to)
{
@@ -107,30 +110,6 @@
return memcmp(digest, msg->cookie, 20);
}
-/* Write an empty message to the pipe
- * so we can bail out from the ConnectNamedPipe call
- */
-static void ping_sig_pipe(int state)
-{
- DWORD read = 0;
- acr_sig_msg_t msg;
-
- signal_handlers_running = state;
- if (IS_INVALID_HANDLE(sig_pipe_handle)) {
- /* Pipe is already closed.
- * Nothing to do.
- */
- return;
- }
- memset(&msg, 0, sizeof(acr_sig_msg_t));
- CallNamedPipeW(sig_pipe_name,
- &msg,
- (DWORD)sizeof(acr_sig_msg_t),
- &msg,
- (DWORD)sizeof(acr_sig_msg_t),
- &read,
- NMPWAIT_NOWAIT);
-}
/* Default signal handler.
*/
@@ -139,7 +118,6 @@
JNIEnv *_E;
switch (sig) {
case SIGKILL:
- ping_sig_pipe(0);
/* Call the System.exit(9)
*/
if (ACR_SystemExit(NULL, sig)) {
@@ -153,7 +131,6 @@
break;
case SIGBUS:
case SIGSEGV:
- ping_sig_pipe(0);
_E = ACR_GetJNIEnv();
if (IS_VALID_HANDLE(_E)) {
(*_E)->FatalError(_E, strsignal(sig));
@@ -241,203 +218,209 @@
return handled;
}
-static DWORD WINAPI read_signal_thread(LPVOID param)
-{
- DWORD read = 0;
- HANDLE pipe = (HANDLE)param;
- acr_sig_msg_t msg;
- memset(&msg, 0, sizeof(acr_sig_msg_t));
- if (!ReadFile(pipe,
- &msg,
- (DWORD)sizeof(acr_sig_msg_t),
- &read,
- NULL)) {
- /* Read failed. */
- goto cleanup;
- }
- if (!signal_handlers_running) {
- /* We just received a message
- * probably from ping_sig_pipe and the
- * signal subsytem is marked for shutdown.
- * Close the pipe and bail out.
- */
- goto cleanup;
- }
- if (read != sizeof(acr_sig_msg_t)) {
- /* Invalid message size.
- */
+static void WINAPI completion_write(DWORD, DWORD, LPOVERLAPPED);
+static void WINAPI completion_sread(DWORD err, DWORD nread,
+ LPOVERLAPPED lpo)
+{
+ sig_pipe_data_t *pd = (sig_pipe_data_t *)lpo;
+ BOOL ws = FALSE;
+
+ if ((err == 0) && (nread == (DWORD)sizeof(acr_sig_msg_t))) {
+ if (verify_security_cookie(&pd->msg, sig_pipe_salt)) {
+ /* Invalid message signature.
+ */
#if defined(DEBUG)
- fprintf(stderr, "Received invalid message size %d\n", read);
- fflush(stderr);
+ fprintf(stderr, "Received invalid message signature\n");
+ fflush(stderr);
#endif
- goto cleanup;
- }
- if (verify_security_cookie(&msg, sig_pipe_salt)) {
- /* Invalid message signature.
+ goto cleanup;
+ }
+ /* Sync with signal handler */
+ EnterCriticalSection(&signal_lock);
+ current_signal_queue |= sigmask(pd->msg.signal);
+ /* Notify the signal monitor thread.
+ * Signal monitor thread will interrupt all waiters
+ * and dispatch the signals if there are no waiters pending.
*/
+ SetEvent(dll_auto_hevent);
+ LeaveCriticalSection(&signal_lock);
+
+ pd->msg.sender = GetCurrentProcessId();
+ ws = WriteFileEx(pd->pipe,
+ &pd->msg,
+ (DWORD)sizeof(acr_sig_msg_t),
+ (LPOVERLAPPED)pd,
+ (LPOVERLAPPED_COMPLETION_ROUTINE)completion_write);
#if defined(DEBUG)
- fprintf(stderr, "Received invalid message signature\n");
- fflush(stderr);
+ if (!ws) {
+ fprintf(stderr, "WriteFileEx failed (%d)\n", GetLastError());
+ fflush(stderr);
+ }
#endif
- goto cleanup;
}
- msg.sender = GetCurrentProcessId();
- /* Write the message back with our pid as sender.
- * We don't care about the result of the write operation.
- */
- WriteFile(pipe, &msg, (DWORD)sizeof(acr_sig_msg_t), &read, NULL);
- FlushFileBuffers(pipe);
- DisconnectNamedPipe(pipe);
- CloseHandle(pipe);
- /* Sync with signal handler */
- EnterCriticalSection(&signal_lock);
- current_signal_queue |= sigmask(msg.signal);
- /* Notify the signal monitor thread.
- * Signal monitor thread will interrupt all waiters
- * and dispatch the signals if there are no waiters pending.
- */
- SetEvent(dll_auto_hevent);
- LeaveCriticalSection(&signal_lock);
- return 0;
cleanup:
- if (IS_VALID_HANDLE(pipe)) {
- DisconnectNamedPipe(pipe);
- CloseHandle(pipe);
+ if (!ws) {
+ DisconnectNamedPipe(pd->pipe);
+ CloseHandle(pd->pipe);
+ x_free(pd);
}
- return 0;
}
-static DWORD WINAPI main_signal_monitor(LPVOID unused)
+static void WINAPI completion_write(DWORD err, DWORD nsend,
+ LPOVERLAPPED lpo)
{
- DWORD rc;
+ sig_pipe_data_t *pd = (sig_pipe_data_t *)lpo;
+ BOOL rs = FALSE;
- while (signal_handlers_running) {
- rc = WaitForSingleObject(dll_auto_hevent, INFINITE);
- if (rc == WAIT_OBJECT_0) {
- /* Dispatch the event to object waiters
- */
- EnterCriticalSection(&signal_lock);
- if (ACR_SIGNAL_NWAITERS() == 0) {
- LeaveCriticalSection(&signal_lock);
- rc = ACR_DeliverSignals();
- if (rc == ACR_INCOMPLETE) {
- /* Signal delivery requires the
- * shutdown
- */
- signal_handlers_running = 0;
- break;
- }
- }
- else {
- LeaveCriticalSection(&signal_lock);
- /* Since we have waiters signal the
- * main interrupt event.
- * Each of the waiters must call
- * ACR_DeliverSignals().
- * The last one will reset the event
- * and the first one will handle the
- * signal queue.
- */
- SetEvent(dll_psig_handle);
- }
- }
- else {
- /* Anything else means we have to exit.
- * Terminate the monitor thread.
- */
- signal_handlers_running = 0;
- break;
+ if ((err == 0) && (nsend == 0)) {
+ rs = ReadFileEx(pd->pipe,
+ &pd->msg,
+ (DWORD)sizeof(acr_sig_msg_t),
+ (LPOVERLAPPED)pd,
+ (LPOVERLAPPED_COMPLETION_ROUTINE)completion_sread);
+#if defined(DEBUG)
+ if (!rs) {
+ fprintf(stderr, "ReadFileEx failed (%d)\n", GetLastError());
+ fflush(stderr);
}
+#endif
+ }
+ if (!rs) {
+ DisconnectNamedPipe(pd->pipe);
+ CloseHandle(pd->pipe);
+ x_free(pd);
}
- return 0;
}
-/* Main signal thread is responsible for handling the
- * listening of external signal messages.
- * Once created it will remain running until application exit,
- * so there is no need for any thread cleanup since we cannot
- * leak a single thread.
- */
-static DWORD WINAPI main_signal_thread(LPVOID unused)
+
+static DWORD sig_pipe_connect(LPOVERLAPPED lpo)
{
-#if defined(DEBUG)
- fprintf(stdout, "\n[native] Initialized signalig subsystem for %d\n",
- GetCurrentProcessId());
- fflush(stdout);
-#endif
+ DWORD rv = 0;
+
+ sig_pipe_handle = CreateNamedPipeW(sig_pipe_name,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES,
+ (DWORD)sizeof(acr_sig_msg_t),
+ (DWORD)sizeof(acr_sig_msg_t),
+ PIPE_TIMEOUT,
+ ACR_GetSaWithNullDacl());
+ if (IS_INVALID_HANDLE(sig_pipe_handle)) {
+ return GetLastError();
+ }
+ if (ConnectNamedPipe(sig_pipe_handle, lpo)) {
+ DWORD ec = GetLastError();
+ /* Overlapped ConnectNamedPipe should return FALSE.
+ */
+ CloseHandle(sig_pipe_handle);
+ return ec;
+ }
+
+ switch (GetLastError()) {
+ case ERROR_IO_PENDING:
+ rv = ERROR_IO_PENDING;
+ break;
+ case ERROR_PIPE_CONNECTED:
+ if (SetEvent(lpo->hEvent))
+ break;
+ default:
+ rv = GetLastError();
+ break;
+ }
+ return rv;
+}
+
+static DWORD WINAPI sig_handler_main(LPVOID unused)
+{
+ OVERLAPPED sync;
+ HANDLE wh[2];
+ DWORD nw = 1;
+ DWORD rc;
+ DWORD cs;
+ sig_pipe_data_t *pd;
+
+ wh[0] = dll_auto_hevent;
+ wh[1] = CreateEvent(NULL, TRUE, TRUE, NULL);
+ if (IS_VALID_HANDLE(wh[1])) {
+ sync.hEvent = wh[1];
+ nw++;
+ cs = sig_pipe_connect(&sync);
+ }
+
while (signal_handlers_running) {
- BOOL connected;
- if (IS_INVALID_HANDLE(sig_pipe_handle)) {
- sig_pipe_handle = CreateNamedPipeW(sig_pipe_name,
- PIPE_ACCESS_DUPLEX, /* ###: We only read */
- PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
- sig_pipe_instances,
- (DWORD)sizeof(acr_sig_msg_t),
- (DWORD)sizeof(acr_sig_msg_t),
- 1000,
- ACR_GetSaWithNullDacl());
- if (IS_INVALID_HANDLE(sig_pipe_handle)) {
- /* Failed to create signal messaging pipe
- * for this process. Retry after 500ms.
+ rc = WaitForMultipleObjectsEx(nw, wh, FALSE, INFINITE, TRUE);
+ switch (rc) {
+ case WAIT_OBJECT_0 + 0:
+ /* Dispatch the event to object waiters
*/
+ EnterCriticalSection(&signal_lock);
+ if (ACR_SIGNAL_NWAITERS() == 0) {
+ LeaveCriticalSection(&signal_lock);
+ rc = ACR_DeliverSignals();
+ if (rc == ACR_INCOMPLETE) {
+ /* Signal delivery requires the
+ * shutdown
+ */
+ signal_handlers_running = 0;
+ }
+ }
+ else {
+ LeaveCriticalSection(&signal_lock);
+ /* Since we have waiters signal the
+ * main interrupt event.
+ * Each of the waiters must call
+ * ACR_DeliverSignals().
+ * The last one will reset the event
+ * and the first one will handle the
+ * signal queue.
+ */
+ SetEvent(dll_psig_handle);
+ }
+
+ break;
+ case WAIT_OBJECT_0 + 1:
+ if (cs == ERROR_IO_PENDING) {
+ DWORD nr = 0;
+ if (!GetOverlappedResult(sig_pipe_handle,
+ &sync,
+ &nr,
+ FALSE)) {
#if defined(DEBUG)
- fprintf(stderr, "Could not create listener pipe '%S' - %d\n",
- sig_pipe_name, GetLastError());
- fflush(stderr);
-#endif
- SleepEx(500, FALSE);
- continue;
- }
- }
-#if defined(DEBUG)
- fprintf(stdout, "Waiting for a client on '%S'\n",
- sig_pipe_name);
- fflush(stdout);
-#endif
- if (!(connected = ConnectNamedPipe(sig_pipe_handle, NULL))) {
- if (GetLastError() == ERROR_PIPE_CONNECTED)
- connected = TRUE;
- }
-#if defined(DEBUG)
- fprintf(stdout, "Client on '%S' is %s\n",
- sig_pipe_name, connected ? "connected" : "not connected");
- fflush(stdout);
+ fprintf(stderr, "Error connecting pipe - %d\n",
+ GetLastError());
+ fflush(stderr);
#endif
- if (connected && signal_handlers_running) {
- /* We have connected client.
- * Start the client worker thread
- */
- HANDLE wt;
- DWORD wi;
- if (!(wt = CreateThread(NULL,
- 0,
- read_signal_thread,
- sig_pipe_handle,
- 0,
- &wi))) {
-
- }
- else
- CloseHandle(wt);
-
- }
- else {
- /* Connect failed.
- * Close the pipe and try again.
- */
- if (connected)
- DisconnectNamedPipe(sig_pipe_handle);
- CloseHandle(sig_pipe_handle);
+ break;
+ }
+ cs = ERROR_SUCCESS;
+ }
+ if (cs == ERROR_SUCCESS) {
+ pd = x_calloc(sizeof(sig_pipe_data_t));
+ if (pd == NULL) {
+ /* ###: Fatal error ?
+ */
+ break;
+ }
+ pd->pipe = sig_pipe_handle;
+ completion_write(0, 0, (LPOVERLAPPED)pd);
+ }
+ cs = sig_pipe_connect(&sync);
+ break;
+ case WAIT_IO_COMPLETION:
+ /* Wait loop interrupt.
+ * This is restartable operation.
+ */
+ break;
+ case WAIT_FAILED:
+ /* One of the events was closed
+ */
+ signal_handlers_running = 0;
+ break;
}
- sig_pipe_handle = INVALID_HANDLE_VALUE;
}
-#if defined(DEBUG)
- fprintf(stdout, "\n[native] Terminated signaling subsystem for %d\n",
- GetCurrentProcessId());
- fflush(stdout);
-#endif
+
return 0;
}
@@ -477,7 +460,11 @@
signal_handlers[SIGKILL] = default_signal_handler;
/* Default handlers for console events.
*/
+#if defined(DEBUG)
+ signal_handlers[SIGINT] = default_signal_handler;
+#else
signal_handlers[SIGINT] = SIG_DFL;
+#endif
signal_handlers[SIGTERM] = SIG_DFL;
signal_handlers[SIGHUP] = SIG_DFL;
@@ -485,40 +472,9 @@
* Combined from pid and ACR_NUMSIG.
*/
pipe_name_from_pid(sig_pipe_name, GetCurrentProcessId(), ACR_NUMSIG);
- sig_pipe_handle = CreateNamedPipeW(sig_pipe_name,
- PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
- sig_pipe_instances,
- (DWORD)sizeof(acr_sig_msg_t),
- (DWORD)sizeof(acr_sig_msg_t),
- 1000,
- ACR_GetSaWithNullDacl());
- if (IS_INVALID_HANDLE(sig_pipe_handle)) {
- /* Failed to create signal messaging pipe
- * for this process. Bail out.
- *
- * ###: We could just continue from here as well.
- * Signal thread wold retry to create this pipe
- * on regular intervals.
- */
- return ACR_GET_OS_ERROR();
- }
if (!(h = CreateThread(NULL,
0,
- main_signal_monitor,
- NULL,
- 0,
- &i))) {
- /* Failed creating thread.
- * If we ever get here the system is
- * unstable and will probably crash
- * in the near future. Anyhow, return the error.
- */
- return ACR_GET_OS_ERROR();
- }
- if (!(h = CreateThread(NULL,
- 0,
- main_signal_thread,
+ sig_handler_main,
NULL,
0,
&i))) {
@@ -562,6 +518,7 @@
/* Someone just entered while we obtained the lock
*/
}
+
while ((mask = (current_signal_queue & ~current_signal_mask))) {
int i;
for (i = 1; i < ACR_NUMSIG; i++) {
Modified: commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c?rev=814773&r1=814772&r2=814773&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c Mon Sep 14 18:35:32 2009
@@ -542,11 +542,13 @@
ppid = atoi(argv[0]);
if (ppid == 0)
return ACR_EINVAL;
+ rc = ACR_RaiseSignal(NULL, SIGINT, ppid);
+ rc = ACR_RaiseSignal(NULL, SIGINT, ppid);
rc = ACR_RaiseSignal(NULL, SIGBUS, ppid);
if (rc) {
char buf[256];
fprintf(stderr, ACR_GetErrorString(rc, buf, sizeof(buf)));
- fputc('\n', stderr);
+ fputc('\n', stderr);
}
}
return 0;