services: Allocate a separate status_changed_event for each service.
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
51f36c220e
commit
039471ec37
|
@ -758,21 +758,21 @@ DWORD __cdecl svcctl_SetServiceStatus(
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
service_lock(service->service_entry);
|
service_lock(service->service_entry);
|
||||||
|
|
||||||
/* FIXME: be a bit more discriminant about what parts of the status we set
|
/* FIXME: be a bit more discriminant about what parts of the status we set
|
||||||
* and check that fields are valid */
|
* and check that fields are valid */
|
||||||
service->service_entry->status = *lpServiceStatus;
|
service->service_entry->status = *lpServiceStatus;
|
||||||
if ((process = service->service_entry->process))
|
SetEvent(service->service_entry->status_changed_event);
|
||||||
{
|
|
||||||
if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
|
if ((process = service->service_entry->process) &&
|
||||||
|
lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
|
||||||
{
|
{
|
||||||
service->service_entry->process = NULL;
|
service->service_entry->process = NULL;
|
||||||
if (!--process->use_count)
|
if (!--process->use_count)
|
||||||
terminate_after_timeout(process, service_kill_timeout);
|
terminate_after_timeout(process, service_kill_timeout);
|
||||||
release_process(process);
|
release_process(process);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
SetEvent(process->status_changed_event);
|
|
||||||
}
|
|
||||||
service_unlock(service->service_entry);
|
service_unlock(service->service_entry);
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
|
|
@ -82,9 +82,6 @@ static DWORD process_create(const WCHAR *name, struct process_entry **entry)
|
||||||
(*entry)->overlapped_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
(*entry)->overlapped_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||||
if (!(*entry)->overlapped_event)
|
if (!(*entry)->overlapped_event)
|
||||||
goto error;
|
goto error;
|
||||||
(*entry)->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
|
||||||
if (!(*entry)->status_changed_event)
|
|
||||||
goto error;
|
|
||||||
(*entry)->control_pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
(*entry)->control_pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
||||||
PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL);
|
PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL);
|
||||||
if ((*entry)->control_pipe == INVALID_HANDLE_VALUE)
|
if ((*entry)->control_pipe == INVALID_HANDLE_VALUE)
|
||||||
|
@ -98,8 +95,6 @@ error:
|
||||||
CloseHandle((*entry)->control_mutex);
|
CloseHandle((*entry)->control_mutex);
|
||||||
if ((*entry)->overlapped_event)
|
if ((*entry)->overlapped_event)
|
||||||
CloseHandle((*entry)->overlapped_event);
|
CloseHandle((*entry)->overlapped_event);
|
||||||
if ((*entry)->status_changed_event)
|
|
||||||
CloseHandle((*entry)->status_changed_event);
|
|
||||||
HeapFree(GetProcessHeap(), 0, *entry);
|
HeapFree(GetProcessHeap(), 0, *entry);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +105,6 @@ static void free_process_entry(struct process_entry *entry)
|
||||||
CloseHandle(entry->control_mutex);
|
CloseHandle(entry->control_mutex);
|
||||||
CloseHandle(entry->control_pipe);
|
CloseHandle(entry->control_pipe);
|
||||||
CloseHandle(entry->overlapped_event);
|
CloseHandle(entry->overlapped_event);
|
||||||
CloseHandle(entry->status_changed_event);
|
|
||||||
HeapFree(GetProcessHeap(), 0, entry);
|
HeapFree(GetProcessHeap(), 0, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +119,13 @@ DWORD service_create(LPCWSTR name, struct service_entry **entry)
|
||||||
HeapFree(GetProcessHeap(), 0, *entry);
|
HeapFree(GetProcessHeap(), 0, *entry);
|
||||||
return ERROR_NOT_ENOUGH_SERVER_MEMORY;
|
return ERROR_NOT_ENOUGH_SERVER_MEMORY;
|
||||||
}
|
}
|
||||||
|
(*entry)->status_changed_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||||
|
if (!(*entry)->status_changed_event)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, (*entry)->name);
|
||||||
|
HeapFree(GetProcessHeap(), 0, *entry);
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
(*entry)->ref_count = 1;
|
(*entry)->ref_count = 1;
|
||||||
(*entry)->status.dwCurrentState = SERVICE_STOPPED;
|
(*entry)->status.dwCurrentState = SERVICE_STOPPED;
|
||||||
(*entry)->status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED;
|
(*entry)->status.dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED;
|
||||||
|
@ -135,6 +136,7 @@ DWORD service_create(LPCWSTR name, struct service_entry **entry)
|
||||||
|
|
||||||
void free_service_entry(struct service_entry *entry)
|
void free_service_entry(struct service_entry *entry)
|
||||||
{
|
{
|
||||||
|
CloseHandle(entry->status_changed_event);
|
||||||
HeapFree(GetProcessHeap(), 0, entry->name);
|
HeapFree(GetProcessHeap(), 0, entry->name);
|
||||||
HeapFree(GetProcessHeap(), 0, entry->config.lpBinaryPathName);
|
HeapFree(GetProcessHeap(), 0, entry->config.lpBinaryPathName);
|
||||||
HeapFree(GetProcessHeap(), 0, entry->config.lpDependencies);
|
HeapFree(GetProcessHeap(), 0, entry->config.lpDependencies);
|
||||||
|
@ -790,6 +792,9 @@ static DWORD service_start_process(struct service_entry *service_entry, struct p
|
||||||
}
|
}
|
||||||
|
|
||||||
service_entry->status.dwCurrentState = SERVICE_START_PENDING;
|
service_entry->status.dwCurrentState = SERVICE_START_PENDING;
|
||||||
|
service_entry->status.dwControlsAccepted = 0;
|
||||||
|
ResetEvent(service_entry->status_changed_event);
|
||||||
|
|
||||||
scmdatabase_add_process(service_entry->db, process);
|
scmdatabase_add_process(service_entry->db, process);
|
||||||
service_entry->process = grab_process(process);
|
service_entry->process = grab_process(process);
|
||||||
process->use_count++;
|
process->use_count++;
|
||||||
|
@ -814,24 +819,20 @@ static DWORD service_start_process(struct service_entry *service_entry, struct p
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD process_wait_for_startup(struct process_entry *process)
|
static DWORD service_wait_for_startup(struct service_entry *service, struct process_entry *process)
|
||||||
{
|
{
|
||||||
HANDLE handles[2] = { process->status_changed_event, process->process };
|
HANDLE handles[2] = { service->status_changed_event, process->process };
|
||||||
DWORD ret;
|
DWORD result;
|
||||||
|
|
||||||
ret = WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout );
|
result = WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout );
|
||||||
return (ret == WAIT_OBJECT_0) ? ERROR_SUCCESS : ERROR_SERVICE_REQUEST_TIMEOUT;
|
if (result != WAIT_OBJECT_0)
|
||||||
}
|
return ERROR_SERVICE_REQUEST_TIMEOUT;
|
||||||
|
|
||||||
static DWORD service_is_running(struct service_entry *service)
|
|
||||||
{
|
|
||||||
DWORD state;
|
|
||||||
|
|
||||||
service_lock(service);
|
service_lock(service);
|
||||||
state = service->status.dwCurrentState;
|
result = service->status.dwCurrentState;
|
||||||
service_unlock(service);
|
service_unlock(service);
|
||||||
|
|
||||||
return (state == SERVICE_START_PENDING || state == SERVICE_RUNNING) ?
|
return (result == SERVICE_START_PENDING || result == SERVICE_RUNNING) ?
|
||||||
ERROR_SUCCESS : ERROR_SERVICE_REQUEST_TIMEOUT;
|
ERROR_SUCCESS : ERROR_SERVICE_REQUEST_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -911,10 +912,7 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *
|
||||||
err = process_send_start_message(process, service->name, service_argv, service_argc);
|
err = process_send_start_message(process, service->name, service_argv, service_argc);
|
||||||
|
|
||||||
if (err == ERROR_SUCCESS)
|
if (err == ERROR_SUCCESS)
|
||||||
err = process_wait_for_startup(process);
|
err = service_wait_for_startup(service, process);
|
||||||
|
|
||||||
if (err == ERROR_SUCCESS)
|
|
||||||
err = service_is_running(service);
|
|
||||||
|
|
||||||
if (err == ERROR_SUCCESS)
|
if (err == ERROR_SUCCESS)
|
||||||
ReleaseMutex(process->control_mutex);
|
ReleaseMutex(process->control_mutex);
|
||||||
|
|
|
@ -43,7 +43,6 @@ struct process_entry
|
||||||
HANDLE control_mutex;
|
HANDLE control_mutex;
|
||||||
HANDLE control_pipe;
|
HANDLE control_pipe;
|
||||||
HANDLE overlapped_event;
|
HANDLE overlapped_event;
|
||||||
HANDLE status_changed_event;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct service_entry
|
struct service_entry
|
||||||
|
@ -53,6 +52,7 @@ struct service_entry
|
||||||
LONG ref_count; /* number of references - if goes to zero and the service is deleted the structure will be freed */
|
LONG ref_count; /* number of references - if goes to zero and the service is deleted the structure will be freed */
|
||||||
LPWSTR name;
|
LPWSTR name;
|
||||||
SERVICE_STATUS status;
|
SERVICE_STATUS status;
|
||||||
|
HANDLE status_changed_event;
|
||||||
QUERY_SERVICE_CONFIGW config;
|
QUERY_SERVICE_CONFIGW config;
|
||||||
DWORD preshutdown_timeout;
|
DWORD preshutdown_timeout;
|
||||||
LPWSTR description;
|
LPWSTR description;
|
||||||
|
|
Loading…
Reference in New Issue