Currently success return from SuspendThread() neither guarantees that thread is already suspended nor that it will be suspended at all. E. g, if SuspendThread is racing with thread normal exit, a SIGUSR1 could be queued to the thread for suspend but it reached exit_thread() and disabled signals for final exit before processing it.
Fixes GRIS game showing embedded Mono's garbage collector error on exit. Which error is due to the race between normal thread exit and GC cleanup. GC cleanup (as well as normal operation actually) first tries to suspend all the threads, failure here is fine. But when suspend succeeded it doesn't tolerate the failure to GetThreadContext() a bit later.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/unix/thread.c | 25 +++++++++++++++++++++---- server/protocol.def | 6 ++++-- server/thread.c | 28 ++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 60c833b0320..19ce0fb28a3 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1611,19 +1611,36 @@ NTSTATUS WINAPI NtOpenThread( HANDLE *handle, ACCESS_MASK access, /****************************************************************************** * NtSuspendThread (NTDLL.@) */ -NTSTATUS WINAPI NtSuspendThread( HANDLE handle, ULONG *count ) +NTSTATUS WINAPI NtSuspendThread( HANDLE handle, ULONG *ret_count ) { - unsigned int ret; + unsigned int ret, count = 0; + HANDLE wait_handle = NULL;
SERVER_START_REQ( suspend_thread ) { req->handle = wine_server_obj_handle( handle ); - if (!(ret = wine_server_call( req ))) + if (!(ret = wine_server_call( req )) || ret == STATUS_PENDING) { - if (count) *count = reply->count; + count = reply->count; + wait_handle = wine_server_ptr_handle( reply->wait_handle ); } } SERVER_END_REQ; + + if (ret == STATUS_PENDING && wait_handle) + { + NtWaitForSingleObject( wait_handle, FALSE, NULL ); + + SERVER_START_REQ( suspend_thread ) + { + req->handle = wine_server_obj_handle( handle ); + req->waited_handle = wine_server_obj_handle( wait_handle ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + } + + if (!ret && ret_count) *ret_count = count; return ret; }
diff --git a/server/protocol.def b/server/protocol.def index 13aea96e796..b26dbc79962 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1107,9 +1107,11 @@ typedef struct
/* Suspend a thread */ @REQ(suspend_thread) - obj_handle_t handle; /* thread handle */ + obj_handle_t handle; /* thread handle */ + obj_handle_t waited_handle; /* handle waited on */ @REPLY - int count; /* new suspend count */ + int count; /* new suspend count */ + obj_handle_t wait_handle; /* handle to wait on */ @END
diff --git a/server/thread.c b/server/thread.c index 56f57cefd8f..c41fd0a02dc 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1550,12 +1550,32 @@ DECL_HANDLER(suspend_thread) { struct thread *thread;
- if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME ))) + if (req->waited_handle) { - if (thread->state == TERMINATED) set_error( STATUS_ACCESS_DENIED ); - else reply->count = suspend_thread( thread ); - release_object( thread ); + struct context *context; + + if (!(context = (struct context *)get_handle_obj( current->process, req->waited_handle, + 0, &context_ops ))) + return; + close_handle( current->process, req->waited_handle ); /* avoid extra server call */ + set_error( context->status ); + release_object( context ); + return; } + + if (!(thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME ))) return; + + if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED ); + else + { + reply->count = suspend_thread( thread ); + if (!get_error() && thread != current && thread->context && thread->context->status == STATUS_PENDING) + { + set_error( STATUS_PENDING ); + reply->wait_handle = alloc_handle( current->process, thread->context, SYNCHRONIZE, 0 ); + } + } + release_object( thread ); }
/* resume a thread */
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=144047
Your paranoid android.
=== debian11b (64 bit WoW report) ===
d3dx10_34: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011C0340. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011E3AC0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011BBC10. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BBC10. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011E3C90.
d3dx10_35: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001239D10. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 0000000001239D10. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 0000000001239D10. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011B6120. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011C3840.
d3dx10_36: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011C3B80. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011C3AB0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011A4A80. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011D58B0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011D5A80.
d3dx10_37: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011BBA30. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011D5840. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D5450. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011D5730. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011D5450.
d3dx10_38: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011BB9A0. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011BB9A0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011A4920. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011E3990. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011BB9A0.
d3dx10_39: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011D6550. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011D67E0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011BD790. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011D5770. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 0000000001195A10.
d3dx10_40: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011D5530. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011BCAB0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D5700. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BC970. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011C3380.
d3dx10_41: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011E3AD0. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011BC970. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011E37F0.
d3dx10_42: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001239D00. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 0000000001239D00. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011E36D0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011B5CB0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011B5E80.
d3dx10_43: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011A4690. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011A4860. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D18E0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011D1AB0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011D55F0.