mirror of
https://github.com/nginx/nginx.git
synced 2024-12-15 05:09:06 +08:00
131 lines
3.0 KiB
C
131 lines
3.0 KiB
C
|
|
/*
|
|
* Copyright (C) Igor Sysoev
|
|
*/
|
|
|
|
|
|
|
|
#define NGX_SERVICE_CONTROL_SHUTDOWN 128
|
|
#define NGX_SERVICE_CONTROL_REOPEN 129
|
|
|
|
|
|
SERVICE_TABLE_ENTRY st[] = {
|
|
{ "nginx", service_main },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
ngx_int_t ngx_service(ngx_log_t *log)
|
|
{
|
|
/* primary thread */
|
|
|
|
/* StartServiceCtrlDispatcher() shouxpdl be called within 30 seconds */
|
|
|
|
if (StartServiceCtrlDispatcher(st) == 0) {
|
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
|
"StartServiceCtrlDispatcher() failed");
|
|
return NGX_ERROR;
|
|
}
|
|
|
|
return NGX_OK;
|
|
}
|
|
|
|
|
|
void service_main(u_int argc, char **argv)
|
|
{
|
|
SERVICE_STATUS status;
|
|
SERVICE_STATUS_HANDLE service;
|
|
|
|
/* thread spawned by SCM */
|
|
|
|
service = RegisterServiceCtrlHandlerEx("nginx", service_handler, ctx);
|
|
if (service == INVALID_HANDLE_VALUE) {
|
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
|
"RegisterServiceCtrlHandlerEx() failed");
|
|
return;
|
|
}
|
|
|
|
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
status.dwCurrentState = SERVICE_START_PENDING;
|
|
status.dwControlsAccepted = SERVICE_ACCEPT_STOP
|
|
|SERVICE_ACCEPT_PARAMCHANGE;
|
|
status.dwWin32ExitCode = NO_ERROR;
|
|
status.dwServiceSpecificExitCode = 0;
|
|
status.dwCheckPoint = 1;
|
|
status.dwWaitHint = 2000;
|
|
|
|
/* SetServiceStatus() should be called within 80 seconds */
|
|
|
|
if (SetServiceStatus(service, &status) == 0) {
|
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
|
"SetServiceStatus() failed");
|
|
return;
|
|
}
|
|
|
|
/* init */
|
|
|
|
status.dwCurrentState = SERVICE_RUNNING;
|
|
status.dwCheckPoint = 0;
|
|
status.dwWaitHint = 0;
|
|
|
|
if (SetServiceStatus(service, &status) == 0) {
|
|
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
|
"SetServiceStatus() failed");
|
|
return;
|
|
}
|
|
|
|
/* call master or worker loop */
|
|
|
|
/*
|
|
* master should use event notification and look status
|
|
* single should use iocp to get notifications from service handler
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
u_int service_handler(u_int control, u_int type, void *data, void *ctx)
|
|
{
|
|
/* primary thread */
|
|
|
|
switch(control) {
|
|
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
status = NGX_IOCP_INTERROGATE;
|
|
break;
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
status = NGX_IOCP_STOP;
|
|
break;
|
|
|
|
case SERVICE_CONTROL_PARAMCHANGE:
|
|
status = NGX_IOCP_RECONFIGURE;
|
|
break;
|
|
|
|
case NGX_SERVICE_CONTROL_SHUTDOWN:
|
|
status = NGX_IOCP_REOPEN;
|
|
break;
|
|
|
|
case NGX_SERVICE_CONTROL_REOPEN:
|
|
status = NGX_IOCP_REOPEN;
|
|
break;
|
|
|
|
default:
|
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
if (ngx_single) {
|
|
if (PostQueuedCompletionStatus(iocp, ... status, ...) == 0) {
|
|
err = ngx_errno;
|
|
ngx_log_error(NGX_LOG_ALERT, log, err,
|
|
"PostQueuedCompletionStatus() failed");
|
|
return err;
|
|
}
|
|
|
|
} else {
|
|
Event
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|