diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c index d4c161655d108aade2ff0cc7536007305263cbab..f47e90b2f95250b3a35403cb0697f2573bdf45e2 100644 --- a/src/sbbs3/services.c +++ b/src/sbbs3/services.c @@ -88,6 +88,8 @@ typedef struct { /* These are run-time state and stat vars */ DWORD clients; SOCKET socket; + BOOL running; + BOOL terminated; } service_t; typedef struct { @@ -264,7 +266,10 @@ js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) strcat(str," "); } - lprintf("%04d %s %s",client->socket,client->service->protocol,str); + if(service==NULL) + lprintf("%04d %s",client->socket,str); + else + lprintf("%04d %s %s",client->socket,client->service->protocol,str); *rval = JSVAL_VOID; return(JS_TRUE); @@ -452,10 +457,55 @@ js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) lprintf("%04d %s !JavaScript %s%s%s: %s",sock,prot,warning,file,line,message); } +/* Server Object Properites */ +enum { + SERVER_PROP_TERMINATED +}; + + +static JSBool js_server_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp) +{ + jsint tiny; + service_client_t* client; + + if((client=(service_client_t*)JS_GetContextPrivate(cx))==NULL) + return(JS_FALSE); + + tiny = JSVAL_TO_INT(id); + + switch(tiny) { + case SERVER_PROP_TERMINATED: +#if 0 + lprintf("%s client->service->terminated=%d" + ,client->service->protocol, client->service->terminated); +#endif + *vp = BOOLEAN_TO_JSVAL(client->service->terminated); + break; + } + + return(JS_TRUE); +} + +#define SERVER_PROP_FLAGS JSPROP_ENUMERATE|JSPROP_READONLY + +static struct JSPropertySpec js_server_properties[] = { +/* name ,tinyid ,flags, getter, setter */ + + { "terminated" ,SERVER_PROP_TERMINATED ,SERVER_PROP_FLAGS, NULL,NULL}, + {0} +}; + static JSClass js_server_class = { - "Server",0, - JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,JS_PropertyStub, - JS_EnumerateStub,JS_ResolveStub,JS_ConvertStub,JS_FinalizeStub + "Server" /* name */ + ,0 /* flags */ + ,JS_PropertyStub /* addProperty */ + ,JS_PropertyStub /* delProperty */ + ,js_server_get /* getProperty */ + ,JS_PropertyStub /* setProperty */ + ,JS_EnumerateStub /* enumerate */ + ,JS_ResolveStub /* resolve */ + ,JS_ConvertStub /* convert */ + ,JS_FinalizeStub /* finalize */ }; static JSContext* @@ -512,7 +562,10 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client, ,NULL,0))==NULL) break; - if(service_client->client==NULL) /* standalone service */ + if(!JS_DefineProperties(js_cx, server, js_server_properties)) + break; + + if(service_client->client==NULL) /* static service */ if(js_CreateSocketObject(js_cx, server, "socket", service_client->socket)==NULL) break; @@ -772,11 +825,12 @@ static void js_service_thread(void* arg) close_socket(socket); } -static void js_standalone_service_thread(void* arg) +static void js_static_service_thread(void* arg) { char spath[MAX_PATH+1]; service_t* service; service_client_t service_client; + SOCKET socket; /* JavaScript-specific */ JSObject* js_glob; JSScript* js_script; @@ -788,7 +842,10 @@ static void js_standalone_service_thread(void* arg) // Copy service_client arg service=(service_t*)arg; - lprintf("%04d %s JavaScript standalone service thread started", service->socket, service->protocol); + service->running=TRUE; + socket = service->socket; + + lprintf("%04d %s static JavaScript service thread started", service->socket, service->protocol); thread_up(TRUE /* setuid */); @@ -826,23 +883,29 @@ static void js_standalone_service_thread(void* arg) JS_DestroyRuntime(js_runtime); thread_down(); - lprintf("%04d %s JavaScript standalone service thread terminated" - ,service->socket, service->protocol); + lprintf("%04d %s static JavaScript service thread terminated" + ,socket, service->protocol); close_socket(service->socket); service->socket=INVALID_SOCKET; + + service->running=FALSE; } -static void native_standalone_service_thread(void* arg) +static void native_static_service_thread(void* arg) { char cmd[MAX_PATH]; char fullcmd[MAX_PATH*2]; + SOCKET socket; SOCKET socket_dup; service_t* service; service = (service_t*)arg; - lprintf("%04d %s standalone service thread started", service->socket, service->protocol); + service->running=TRUE; + socket = service->socket; + + lprintf("%04d %s static service thread started", socket, service->protocol); thread_up(TRUE /* setuid */); @@ -855,7 +918,7 @@ static void native_standalone_service_thread(void* arg) TRUE, // Inheritable DUPLICATE_SAME_ACCESS)) { lprintf("%04d !%s ERROR %d duplicating socket descriptor" - ,service->socket,service->protocol,GetLastError()); + ,socket,service->protocol,GetLastError()); close_socket(service->socket); service->socket=INVALID_SOCKET; thread_down(); @@ -875,12 +938,14 @@ static void native_standalone_service_thread(void* arg) system(fullcmd); thread_down(); - lprintf("%04d %s standalone service thread terminated" + lprintf("%04d %s static service thread terminated" ,socket, service->protocol); close_socket(service->socket); service->socket=INVALID_SOCKET; closesocket(socket_dup); /* close duplicate handle */ + + service->running=FALSE; } static void native_service_thread(void* arg) @@ -1124,6 +1189,7 @@ void DLLCALL services_thread(void* arg) int result; int optval; ulong total_clients; + ulong total_running; time_t t; time_t initialized=0; fd_set socket_set; @@ -1305,18 +1371,18 @@ void DLLCALL services_thread(void* arg) return; } - /* Setup standalone service threads */ + /* Setup static service threads */ for(i=0;i<(int)services;i++) { - if(!(service[i].options&SERVICE_OPT_STANDALONE)) + if(!(service[i].options&SERVICE_OPT_STATIC)) continue; /* start thread here */ SAFECOPY(cmd,service[i].cmd); strlwr(cmd); if(strstr(cmd,".js")) /* JavaScript */ - _beginthread(js_standalone_service_thread, 0, &service[i]); + _beginthread(js_static_service_thread, 0, &service[i]); else /* Native */ - _beginthread(native_standalone_service_thread, 0, &service[i]); + _beginthread(native_static_service_thread, 0, &service[i]); } /* signal caller that we've started up successfully */ @@ -1361,7 +1427,7 @@ void DLLCALL services_thread(void* arg) FD_ZERO(&socket_set); high_socket=0; for(i=0;i<(int)services;i++) { - if(service[i].options&SERVICE_OPT_STANDALONE) + if(service[i].options&SERVICE_OPT_STATIC) continue; if(service[i].socket==INVALID_SOCKET) continue; @@ -1549,13 +1615,15 @@ void DLLCALL services_thread(void* arg) } /* Close Service Sockets */ + lprintf("0000 Closing service sockets"); for(i=0;i<(int)services;i++) { + service[i].terminated=TRUE; if(service[i].socket!=INVALID_SOCKET) close_socket(service[i].socket); service[i].socket=INVALID_SOCKET; } - /* Wait for Service Threads to terminate */ + /* Wait for Dynamic Service Threads to terminate */ total_clients=0; for(i=0;i<(int)services;i++) total_clients+=service[i].clients; @@ -1572,6 +1640,23 @@ void DLLCALL services_thread(void* arg) lprintf("0000 Done waiting"); } + /* Wait for Static Service Threads to terminate */ + total_running=0; + for(i=0;i<(int)services;i++) + total_running+=service[i].running; + if(total_running) { + lprintf("0000 Waiting for %d static services to terminate",total_running); + while(1) { + total_running=0; + for(i=0;i<(int)services;i++) + total_running+=service[i].running; + if(!total_running) + break; + mswait(500); + } + lprintf("0000 Done waiting"); + } + /* Free Service Data */ services=0; free(service);