services: Unlink process immediately after service stopped.
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
46b2746938
commit
fac8ec9389
|
@ -100,21 +100,17 @@ struct timeout_queue_elem
|
||||||
struct list entry;
|
struct list entry;
|
||||||
|
|
||||||
FILETIME time;
|
FILETIME time;
|
||||||
void (*func)(struct process_entry *);
|
|
||||||
struct process_entry *process;
|
struct process_entry *process;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void run_after_timeout(void (*func)(struct process_entry *), struct process_entry *process, DWORD timeout)
|
static void terminate_after_timeout(struct process_entry *process, DWORD timeout)
|
||||||
{
|
{
|
||||||
struct timeout_queue_elem *elem = HeapAlloc(GetProcessHeap(), 0, sizeof(struct timeout_queue_elem));
|
struct timeout_queue_elem *elem;
|
||||||
ULARGE_INTEGER time;
|
ULARGE_INTEGER time;
|
||||||
|
|
||||||
if(!elem) {
|
if (!(elem = HeapAlloc(GetProcessHeap(), 0, sizeof(*elem))))
|
||||||
func(process);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
elem->func = func;
|
|
||||||
elem->process = grab_process(process);
|
elem->process = grab_process(process);
|
||||||
|
|
||||||
GetSystemTimeAsFileTime(&elem->time);
|
GetSystemTimeAsFileTime(&elem->time);
|
||||||
|
@ -765,7 +761,11 @@ DWORD __cdecl svcctl_SetServiceStatus(
|
||||||
if ((process = service->service_entry->process))
|
if ((process = service->service_entry->process))
|
||||||
{
|
{
|
||||||
if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
|
if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
|
||||||
run_after_timeout(process_terminate, process, service_kill_timeout);
|
{
|
||||||
|
service->service_entry->process = NULL;
|
||||||
|
terminate_after_timeout(process, service_kill_timeout);
|
||||||
|
release_process(process);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
SetEvent(process->status_changed_event);
|
SetEvent(process->status_changed_event);
|
||||||
}
|
}
|
||||||
|
@ -1943,7 +1943,7 @@ DWORD events_loop(void)
|
||||||
(err > WAIT_OBJECT_0 + 1 && idx == err - WAIT_OBJECT_0 - 2))
|
(err > WAIT_OBJECT_0 + 1 && idx == err - WAIT_OBJECT_0 - 2))
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(&timeout_queue_cs);
|
LeaveCriticalSection(&timeout_queue_cs);
|
||||||
iter->func(iter->process);
|
process_terminate(iter->process);
|
||||||
EnterCriticalSection(&timeout_queue_cs);
|
EnterCriticalSection(&timeout_queue_cs);
|
||||||
|
|
||||||
release_process(iter->process);
|
release_process(iter->process);
|
||||||
|
@ -1975,7 +1975,7 @@ DWORD events_loop(void)
|
||||||
LIST_FOR_EACH_ENTRY_SAFE(iter, iter_safe, &timeout_queue, struct timeout_queue_elem, entry)
|
LIST_FOR_EACH_ENTRY_SAFE(iter, iter_safe, &timeout_queue, struct timeout_queue_elem, entry)
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(&timeout_queue_cs);
|
LeaveCriticalSection(&timeout_queue_cs);
|
||||||
iter->func(iter->process);
|
process_terminate(iter->process);
|
||||||
EnterCriticalSection(&timeout_queue_cs);
|
EnterCriticalSection(&timeout_queue_cs);
|
||||||
|
|
||||||
release_process(iter->process);
|
release_process(iter->process);
|
||||||
|
|
|
@ -321,7 +321,9 @@ static DWORD WINAPI pipe_thread(void *arg)
|
||||||
static void test_service(void)
|
static void test_service(void)
|
||||||
{
|
{
|
||||||
SC_HANDLE service_handle = register_service("simple_service");
|
SC_HANDLE service_handle = register_service("simple_service");
|
||||||
|
SERVICE_STATUS_PROCESS status2;
|
||||||
SERVICE_STATUS status;
|
SERVICE_STATUS status;
|
||||||
|
DWORD bytes;
|
||||||
BOOL res;
|
BOOL res;
|
||||||
|
|
||||||
if(!service_handle)
|
if(!service_handle)
|
||||||
|
@ -349,6 +351,11 @@ static void test_service(void)
|
||||||
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
|
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
|
||||||
todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
|
todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
|
||||||
|
|
||||||
|
res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes);
|
||||||
|
ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError());
|
||||||
|
ok(status2.dwCurrentState == SERVICE_RUNNING, "status2.dwCurrentState = %x\n", status2.dwCurrentState);
|
||||||
|
ok(status2.dwProcessId != 0, "status2.dwProcessId = %d\n", status2.dwProcessId);
|
||||||
|
|
||||||
res = ControlService(service_handle, 128, &status);
|
res = ControlService(service_handle, 128, &status);
|
||||||
ok(res, "ControlService failed: %u\n", GetLastError());
|
ok(res, "ControlService failed: %u\n", GetLastError());
|
||||||
expect_event("CUSTOM");
|
expect_event("CUSTOM");
|
||||||
|
@ -366,7 +373,9 @@ static void test_service(void)
|
||||||
static inline void test_no_stop(void)
|
static inline void test_no_stop(void)
|
||||||
{
|
{
|
||||||
SC_HANDLE service_handle = register_service("no_stop");
|
SC_HANDLE service_handle = register_service("no_stop");
|
||||||
|
SERVICE_STATUS_PROCESS status2;
|
||||||
SERVICE_STATUS status;
|
SERVICE_STATUS status;
|
||||||
|
DWORD bytes;
|
||||||
BOOL res;
|
BOOL res;
|
||||||
|
|
||||||
if(!service_handle)
|
if(!service_handle)
|
||||||
|
@ -397,6 +406,11 @@ static inline void test_no_stop(void)
|
||||||
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
|
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
|
||||||
todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
|
todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
|
||||||
|
|
||||||
|
res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes);
|
||||||
|
ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError());
|
||||||
|
ok(status2.dwCurrentState == SERVICE_RUNNING, "status2.dwCurrentState = %x\n", status2.dwCurrentState);
|
||||||
|
ok(status2.dwProcessId != 0, "status2.dwProcessId = %d\n", status2.dwProcessId);
|
||||||
|
|
||||||
res = ControlService(service_handle, SERVICE_CONTROL_STOP, &status);
|
res = ControlService(service_handle, SERVICE_CONTROL_STOP, &status);
|
||||||
ok(res, "ControlService failed: %u\n", GetLastError());
|
ok(res, "ControlService failed: %u\n", GetLastError());
|
||||||
expect_event("STOP");
|
expect_event("STOP");
|
||||||
|
@ -413,6 +427,11 @@ static inline void test_no_stop(void)
|
||||||
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
|
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
|
||||||
ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
|
ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
|
||||||
|
|
||||||
|
res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes);
|
||||||
|
ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError());
|
||||||
|
ok(status2.dwProcessId == 0 || broken(status2.dwProcessId != 0),
|
||||||
|
"status2.dwProcessId = %d\n", status2.dwProcessId);
|
||||||
|
|
||||||
res = DeleteService(service_handle);
|
res = DeleteService(service_handle);
|
||||||
ok(res, "DeleteService failed: %u\n", GetLastError());
|
ok(res, "DeleteService failed: %u\n", GetLastError());
|
||||||
|
|
||||||
|
@ -428,6 +447,11 @@ static inline void test_no_stop(void)
|
||||||
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
|
ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
|
||||||
ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
|
ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
|
||||||
|
|
||||||
|
res = QueryServiceStatusEx(service_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status2, sizeof(status2), &bytes);
|
||||||
|
ok(res, "QueryServiceStatusEx failed: %u\n", GetLastError());
|
||||||
|
ok(status2.dwProcessId == 0 || broken(status2.dwProcessId != 0),
|
||||||
|
"status2.dwProcessId = %d\n", status2.dwProcessId);
|
||||||
|
|
||||||
CloseServiceHandle(service_handle);
|
CloseServiceHandle(service_handle);
|
||||||
|
|
||||||
res = QueryServiceStatus(service_handle, &status);
|
res = QueryServiceStatus(service_handle, &status);
|
||||||
|
|
Loading…
Reference in New Issue