From b5c1a8f635f2f8f8ccf7c85ad52c40a632711a03 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Mon, 9 Apr 2018 19:29:02 +0800 Subject: [PATCH] services: Add a 3000 ms timeout to StartService. Signed-off-by: Dmitry Timoshkov Signed-off-by: Alexandre Julliard --- programs/services/rpc.c | 4 ++-- programs/services/services.c | 15 ++++++++++++--- programs/services/services.h | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/programs/services/rpc.c b/programs/services/rpc.c index 5ecd6601a56..efbcd7645b9 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -1212,7 +1212,7 @@ DWORD __cdecl svcctl_StartServiceW( if (service->service_entry->config.dwStartType == SERVICE_DISABLED) return ERROR_SERVICE_DISABLED; - if (!scmdatabase_lock_startup(service->service_entry->db)) + if (!scmdatabase_lock_startup(service->service_entry->db, 3000)) return ERROR_SERVICE_DATABASE_LOCKED; err = service_start(service->service_entry, dwNumServiceArgs, lpServiceArgVectors); @@ -1374,7 +1374,7 @@ DWORD __cdecl svcctl_LockServiceDatabase( if ((err = validate_scm_handle(hSCManager, SC_MANAGER_LOCK, &manager)) != ERROR_SUCCESS) return err; - if (!scmdatabase_lock_startup(manager->db)) + if (!scmdatabase_lock_startup(manager->db, 0)) return ERROR_SERVICE_DATABASE_LOCKED; lock = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sc_lock)); diff --git a/programs/services/services.c b/programs/services/services.c index f7c47b5bc23..eba98d6ee88 100644 --- a/programs/services/services.c +++ b/programs/services/services.c @@ -361,7 +361,7 @@ static void scmdatabase_autostart_services(struct scmdatabase *db) scmdatabase_unlock(db); qsort(services_list, size, sizeof(services_list[0]), compare_tags); - while (!scmdatabase_lock_startup(db)) Sleep(10); + scmdatabase_lock_startup(db, INFINITE); for (i = 0; i < size; i++) { @@ -619,9 +619,18 @@ static DWORD scmdatabase_load_services(struct scmdatabase *db) return ERROR_SUCCESS; } -BOOL scmdatabase_lock_startup(struct scmdatabase *db) +BOOL scmdatabase_lock_startup(struct scmdatabase *db, int timeout) { - return !InterlockedCompareExchange(&db->service_start_lock, TRUE, FALSE); + while (InterlockedCompareExchange(&db->service_start_lock, TRUE, FALSE)) + { + if (timeout != INFINITE) + { + timeout -= 10; + if (timeout <= 0) return FALSE; + } + Sleep(10); + } + return TRUE; } void scmdatabase_unlock_startup(struct scmdatabase *db) diff --git a/programs/services/services.h b/programs/services/services.h index fd19ed32f4b..5a79c35778a 100644 --- a/programs/services/services.h +++ b/programs/services/services.h @@ -77,7 +77,7 @@ struct service_entry *scmdatabase_find_service(struct scmdatabase *db, LPCWSTR n struct service_entry *scmdatabase_find_service_by_displayname(struct scmdatabase *db, LPCWSTR name); DWORD scmdatabase_add_service(struct scmdatabase *db, struct service_entry *entry); -BOOL scmdatabase_lock_startup(struct scmdatabase *db); +BOOL scmdatabase_lock_startup(struct scmdatabase *db, int timeout); void scmdatabase_unlock_startup(struct scmdatabase *db); void scmdatabase_lock(struct scmdatabase *db);