wine-staging/patches/ntdll-Threading/0001-ntdll-Fix-race-condition-when-threads-are-killed-dur.patch

57 lines
1.9 KiB
Diff
Raw Normal View History

From 5f34c6a4429025ee71616e677e0e59342bee17b0 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 25 Feb 2015 22:45:42 +0100
2018-02-17 16:59:43 -08:00
Subject: [PATCH] ntdll: Fix race-condition when threads are killed during
shutdown.
When exit_thread is executed, nb_threads is decremented before the thread is
fully shutdown. When another thread runs ExitProcess() this will cause a SIGQUIT
signal to all threads, effectively decrementing nb_threads twice. The process
will terminate with a wrong exitcode then because the refcount reaches zero too
early.
Currently Wine has no locking protection of LdrShutdownProcess(), so it can
only be executed safely when all other threads have terminated before. Most
likely there are more Wine bugs in this area, but the attached patch should
fix the most critical one (messed up refcounting of threads) for now.
---
2020-05-04 20:44:11 -07:00
dlls/ntdll/thread.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index bb11521cf69..fee26ccd21d 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -298,6 +298,7 @@ TEB *thread_init(void)
2018-02-17 16:59:43 -08:00
void WINAPI RtlExitUserThread( ULONG status )
{
static void *prev_teb;
+ sigset_t sigset;
TEB *teb;
if (status) /* send the exit code to the server (0 is already the default) */
@@ -311,7 +312,7 @@ void WINAPI RtlExitUserThread( ULONG status )
2020-05-04 20:44:11 -07:00
SERVER_END_REQ;
}
- if (InterlockedDecrement( &nb_threads ) <= 0)
+ if (InterlockedCompareExchange( &nb_threads, 0, 0 ) <= 0)
{
LdrShutdownProcess();
unix_funcs->exit_process( status );
@@ -333,6 +334,11 @@ void WINAPI RtlExitUserThread( ULONG status )
}
}
+ sigemptyset( &sigset );
+ sigaddset( &sigset, SIGQUIT );
+ pthread_sigmask( SIG_BLOCK, &sigset, NULL );
2020-05-04 20:44:11 -07:00
+ if (!InterlockedDecrement( &nb_threads )) _exit( status );
+
for (;;) unix_funcs->exit_thread( status );
2018-02-17 16:59:43 -08:00
}
--
2.26.2