Commit fac8ec93 authored by Sebastian Lackner's avatar Sebastian Lackner Committed by Alexandre Julliard

services: Unlink process immediately after service stopped.

parent 46b27469
...@@ -100,21 +100,17 @@ struct timeout_queue_elem ...@@ -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( ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment