From: Rémi Bernon rbernon@codeweavers.com
Fixes: 672c3a561f5cd1cd6937c702fe2fe05397f41375 --- dlls/kernel32/tests/sync.c | 64 ++++++++++++++++++++++++++++++++++++-- server/mutex.c | 5 +-- 2 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index eb13fd15485..e548219569a 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -228,12 +228,35 @@ static void test_temporary_objects(void) ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError()); }
+struct test_mutex_thread_params +{ + HANDLE mutex; + HANDLE start_event; + HANDLE stop_event; + BOOL owner; +}; + +static DWORD WINAPI test_mutex_thread(void *arg) +{ + struct test_mutex_thread_params *params = arg; + DWORD ret; + + ret = WaitForSingleObject(params->mutex, INFINITE); + if (params->owner) ok(!ret, "got %#lx\n", ret); + else ok(ret == ERROR_WAIT_NO_CHILDREN, "got %#lx\n", ret); + SetEvent(params->start_event); + + ret = WaitForSingleObject(params->stop_event, INFINITE); + ok(!ret, "got %#lx\n", ret); + return 0; +} + static void test_mutex(void) { DWORD wait_ret; BOOL ret; - HANDLE hCreated; - HANDLE hOpened; + HANDLE hCreated, hOpened, owner_thread, waiter_thread; + struct test_mutex_thread_params params; int i; DWORD failed = 0;
@@ -336,6 +359,43 @@ static void test_mutex(void) CloseHandle(hOpened);
CloseHandle(hCreated); + + params.start_event = CreateEventW(NULL, FALSE, FALSE, NULL); + params.stop_event = CreateEventW(NULL, FALSE, FALSE, NULL); + params.mutex = CreateMutexA(NULL, FALSE, NULL); + + params.owner = TRUE; + owner_thread = CreateThread(NULL, 0, test_mutex_thread, ¶ms, 0, NULL); + ok(!!owner_thread, "CreateThread failed, error %lu\n", GetLastError()); + ret = WaitForSingleObject(params.start_event, 1000); + ok(!ret, "got %#x\n", ret); + + params.owner = FALSE; + waiter_thread = CreateThread(NULL, 0, test_mutex_thread, ¶ms, 0, NULL); + ok(!!waiter_thread, "CreateThread failed, error %lu\n", GetLastError()); + ret = WaitForSingleObject(params.start_event, 100); + ok(ret == WAIT_TIMEOUT, "got %#x\n", ret); + + CloseHandle(params.mutex); + ret = WaitForSingleObject(params.start_event, 100); + ok(ret == WAIT_TIMEOUT, "got %#x\n", ret); + + TerminateThread(owner_thread, 0); + ret = WaitForSingleObject(owner_thread, 1000); + ok(!ret, "got %#x\n", ret); + ret = WaitForSingleObject(params.start_event, 1000); + ok(!ret, "got %#x\n", ret); + + SetEvent(params.stop_event); + ret = WaitForSingleObject(waiter_thread, 1000); + ok(!ret, "got %#x\n", ret); + + CloseHandle(owner_thread); + CloseHandle(waiter_thread); + + CloseHandle(params.start_event); + CloseHandle(params.stop_event); + CloseHandle(params.mutex); }
static void test_slist(void) diff --git a/server/mutex.c b/server/mutex.c index 573fcda1083..e370d301472 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -97,6 +97,7 @@ static void do_grab( struct mutex_sync *mutex, struct thread *thread ) if (!mutex->count++) /* FIXME: avoid wrap-around */ { assert( !mutex->owner ); + grab_object( mutex ); mutex->owner = thread; list_add_head( &thread->mutex_list, &mutex->entry ); } @@ -116,6 +117,7 @@ static int do_release( struct mutex_sync *mutex, struct thread *thread, int coun list_remove( &mutex->entry ); mutex->owner = NULL; wake_up( &mutex->obj, 0 ); + release_object( mutex ); } return 1; } @@ -131,8 +133,7 @@ static void mutex_sync_destroy( struct object *obj ) { struct mutex_sync *mutex = (struct mutex_sync *)obj; assert( obj->ops == &mutex_sync_ops ); - - if (mutex->count) do_release( mutex, current, mutex->count ); + assert( !mutex->count ); }
static int mutex_sync_signaled( struct object *obj, struct wait_queue_entry *entry )