diff --git a/include/empthread.h b/include/empthread.h index a59acdb1..800f2208 100644 --- a/include/empthread.h +++ b/include/empthread.h @@ -105,6 +105,7 @@ typedef struct { typedef struct loc_Thread_t empth_t; typedef struct loc_Sem_t empth_sem_t; +void empth_request_shutdown(void); #endif int empth_init(char **ctx, int flags); diff --git a/include/prototypes.h b/include/prototypes.h index a3d1b848..6940f1ab 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -445,7 +445,7 @@ extern int command(void); extern int recvclient(s_char *, int); /* service.c */ -extern int service_stopped(void); +extern void stop_service(void); /* more in service.h */ /* diff --git a/src/lib/empthread/ntthread.c b/src/lib/empthread/ntthread.c index cb34d6db..41af8852 100644 --- a/src/lib/empthread/ntthread.c +++ b/src/lib/empthread/ntthread.c @@ -126,6 +126,10 @@ static struct { /* We use this to lockstep when we are starting up threads. */ HANDLE hThreadStartEvent; + /* This is an event used to wakeup the main thread */ + /* to start the shutdown sequence. */ + HANDLE hShutdownEvent; + /* The Thread Local Storage index. We store the pThread pointer */ /* for each thread at this index. */ DWORD dwTLSIndex; @@ -281,6 +285,58 @@ loc_SleepThisThread(unsigned long ulMillisecs) } +/************************ + * loc_Ctrl_C_Handler + * + * Ctrl-C will initiate a shutdown. This is done by calling + * empth_request_shutdown() + */ +static BOOL +loc_Ctrl_C_Handler(DWORD fdwCtrlType) +{ + switch (fdwCtrlType) + { + // Handle the CTRL+C signal. + case CTRL_C_EVENT: + empth_request_shutdown(); + return TRUE; + + case CTRL_CLOSE_EVENT: + case CTRL_BREAK_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + default: + return FALSE; + } +} + +/************************ + * empth_request_shutdown + * + * This wakes up the main thread so shutdown can proceed. + * This is done by signalling hShutdownEvent. + */ +void +empth_request_shutdown(void) +{ + SetEvent(loc_GVAR.hShutdownEvent); +} + +/************************ + * loc_BlockMainThread + * + * This blocks up the main thread. + * loc_WakeupMainThread() is used + * wakeup the main so shutdown can + * proceed. + */ +static void +loc_BlockMainThread(void) +{ + /* Get the MUTEX semaphore, wait the number of MS */ + WaitForSingleObject(loc_GVAR.hShutdownEvent, INFINITE); +} + /************************ * empth_threadMain * @@ -344,7 +400,7 @@ empth_init(char **ctx_ptr, int flags) /* Initally unowned. */ loc_GVAR.hThreadMutex = CreateMutex(NULL, FALSE, NULL); if (!loc_GVAR.hThreadMutex) { - logerror("Failed to create mutex"); + logerror("Failed to create mutex %d", GetLastError()); return 0; } @@ -352,10 +408,19 @@ empth_init(char **ctx_ptr, int flags) /* Automatic state reset. */ loc_GVAR.hThreadStartEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (!loc_GVAR.hThreadStartEvent) { - logerror("Failed to create mutex"); + logerror("Failed to create start event %d", GetLastError()); return 0; } + /* Create the shutdown event for the main thread. */ + /* Manual reset */ + loc_GVAR.hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!loc_GVAR.hShutdownEvent) { + logerror("Failed to create shutdown event %d", GetLastError()); + return 0; + } + SetConsoleCtrlHandler((PHANDLER_ROUTINE)loc_Ctrl_C_Handler, TRUE); + /* Create the global Thread context. */ pThread = (loc_Thread_t *)malloc(sizeof(*pThread)); if (!pThread) { @@ -469,17 +534,7 @@ empth_exit(void) loc_debug("empth_exit"); if (pThread->bMainThread) { - if (daemonize) - service_stopped(); /* Wait until the service is stopped */ - else { - while (1) { /* server UI - Wait forever. */ - char buf[20]; - printf("\nEmpire Server>"); - fgets(buf, sizeof(buf), stdin); - if (!strnicmp(buf, "quit", 4)) - break; - } - } + loc_BlockMainThread(); loc_RunThisThread(); shutdwn(0); } else { diff --git a/src/lib/gen/service.c b/src/lib/gen/service.c index a33dd41d..a9652c82 100644 --- a/src/lib/gen/service.c +++ b/src/lib/gen/service.c @@ -149,7 +149,6 @@ remove_service(char *service_name) static SERVICE_STATUS service_status; static SERVICE_STATUS_HANDLE service_status_handle; -static HANDLE hShutdownEvent = NULL; void WINAPI service_ctrl_handler(DWORD Opcode) @@ -168,7 +167,7 @@ service_ctrl_handler(DWORD Opcode) case SERVICE_CONTROL_STOP: logerror("Service stopping"); - SetEvent(hShutdownEvent); + empth_request_shutdown(); return; case SERVICE_CONTROL_INTERROGATE: @@ -206,12 +205,6 @@ service_main(DWORD argc, LPTSTR *argv) return; } - if ((hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { - logerror("CreateEvent for Shutdown failed %d\n", GetLastError()); - finish_server(); - return; - } - start_server(0); /* Initialization complete - report running status. */ @@ -229,14 +222,6 @@ service_main(DWORD argc, LPTSTR *argv) finish_server(); } -void -service_stopped(void) -{ - if (hShutdownEvent != NULL) { - WaitForSingleObject(hShutdownEvent,INFINITE); - } -} - void stop_service(void) {