[PATCH v3 0/7] MR9579: ntdll: On macOS, transform the main thread into a Wine thread (running a CFRunLoop) on launch.
Currently, the process's main thread runs `main()` -> `__wine_main()` -> `apple_main_thread()` -> `CFRunLoopRun()`. A run loop source is added that creates the Wine main thread and runs `start_main_thread()`. With this MR, the Wine main thread calls `transform_mac_main_thread()` in `server_init_process()`. That essentially calls `NtCreateThreadEx()`, but instead of creating a new pthread it adds a source to the main thread run loop to run `start_thread()`. This transforms the process main thread into a Wine thread, after that it calls the PE `__wine_mac_run_cfrunloop()` in ntdll. That does a run_mac_cfrunloop Unix call, which just runs `CFRunLoopRun()`. The process main thread is now a Wine thread, but is otherwise still a normal Mac application main thread (including the ability for winemac to transform into a Cocoa application). In theory it might be possible to avoid the initial `CFRunLoopRun()` and have `apple_main_thread()` just spawn the Wine main thread and wait to run `start_thread()`, but the extra `CFRunLoopRun()` on the stack doesn't hurt anything. An exception/crash on the process main thread will be caught like a normal syscall fault, but `__wine_mac_run_cfrunloop()` prints an error and terminates the process. I think this is an improvement over the current behavior, which is a segfault in the signal handler when it tries to access the non-existent TEB that results in the thread hanging and eating 100% CPU. (Arguably it would be even better to unregister the signal handler and re-throw the signal so the user gets a normal macOS crash report with a helpful backtrace, maybe this could be done later.) Besides exception handling, having the main thread be a Wine thread will also allow the full use of Wine logging functions (!9503), and should allow winemac to be simplified (where many AppKit functions must be called from the main thread, and events are delivered to the main thread). -- v3: ntdll: On macOS, transform the main thread into a Wine thread (running a CFRunLoop) on launch. ntdll: Get a pointer to the PE __wine_mac_run_cfrunloop on the Unix side. ntdll: Add __wine_mac_run_cfrunloop to the PE side and export it. ntdll: Add Unix call to run a CFRunLoop. ntdll: Make thread creation helper an argument to create_thread. ntdll: Move all of NtCreateThreadEx into a helper. ntdll: Factor pthread creation out of NtCreateThreadEx. https://gitlab.winehq.org/wine/wine/-/merge_requests/9579
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/unix/thread.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index cba34ed8ca7..b72a990a252 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1310,6 +1310,29 @@ static NTSTATUS update_attr_list( PS_ATTRIBUTE_LIST *attr, HANDLE thread, const return status; } + +/*********************************************************************** + * create_pthread + */ +static NTSTATUS create_pthread( struct ntdll_thread_data *thread_data, TEB *teb ) +{ + pthread_t pthread_id; + pthread_attr_t pthread_attr; + NTSTATUS status = STATUS_SUCCESS; + + pthread_attr_init( &pthread_attr ); + pthread_attr_setstack( &pthread_attr, thread_data->kernel_stack, kernel_stack_size ); + pthread_attr_setguardsize( &pthread_attr, 0 ); + pthread_attr_setscope( &pthread_attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ + + if (pthread_create( &pthread_id, &pthread_attr, (void * (*)(void *))start_thread, teb )) + status = STATUS_NO_MEMORY; + + pthread_attr_destroy( &pthread_attr ); + return status; +} + + /*********************************************************************** * NtCreateThread (NTDLL.@) */ @@ -1334,8 +1357,6 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER | THREAD_CREATE_FLAGS_SKIP_LOADER_INIT | THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE; sigset_t sigset; - pthread_t pthread_id; - pthread_attr_t pthread_attr; data_size_t len; struct object_attributes *objattr; struct ntdll_thread_data *thread_data; @@ -1442,18 +1463,12 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT thread_data->start = start; thread_data->param = param; - pthread_attr_init( &pthread_attr ); - pthread_attr_setstack( &pthread_attr, thread_data->kernel_stack, kernel_stack_size ); - pthread_attr_setguardsize( &pthread_attr, 0 ); - pthread_attr_setscope( &pthread_attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ InterlockedIncrement( &nb_threads ); - if (pthread_create( &pthread_id, &pthread_attr, (void * (*)(void *))start_thread, teb )) + if ((status = create_pthread( thread_data, teb ))) { InterlockedDecrement( &nb_threads ); virtual_free_teb( teb ); - status = STATUS_NO_MEMORY; } - pthread_attr_destroy( &pthread_attr ); done: pthread_sigmask( SIG_SETMASK, &sigset, NULL ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9579
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/unix/thread.c | 46 +++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index b72a990a252..f13d999ec9e 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1334,24 +1334,12 @@ static NTSTATUS create_pthread( struct ntdll_thread_data *thread_data, TEB *teb /*********************************************************************** - * NtCreateThread (NTDLL.@) - */ -NTSTATUS WINAPI NtCreateThread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, - HANDLE process, CLIENT_ID *id, CONTEXT *ctx, INITIAL_TEB *teb, - BOOLEAN suspended ) -{ - FIXME( "%p %d %p %p %p %p %p %d, stub!\n", - handle, access, attr, process, id, ctx, teb, suspended ); - return STATUS_NOT_IMPLEMENTED; -} - -/*********************************************************************** - * NtCreateThreadEx (NTDLL.@) + * create_thread */ -NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, - HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, - ULONG flags, ULONG_PTR zero_bits, SIZE_T stack_commit, - SIZE_T stack_reserve, PS_ATTRIBUTE_LIST *attr_list ) +static NTSTATUS create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, + ULONG flags, ULONG_PTR zero_bits, SIZE_T stack_commit, + SIZE_T stack_reserve, PS_ATTRIBUTE_LIST *attr_list ) { static const ULONG supported_flags = THREAD_CREATE_FLAGS_CREATE_SUSPENDED | THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH | THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER | THREAD_CREATE_FLAGS_SKIP_LOADER_INIT | @@ -1482,6 +1470,30 @@ done: return status; } +/*********************************************************************** + * NtCreateThread (NTDLL.@) + */ +NTSTATUS WINAPI NtCreateThread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + HANDLE process, CLIENT_ID *id, CONTEXT *ctx, INITIAL_TEB *teb, + BOOLEAN suspended ) +{ + FIXME( "%p %d %p %p %p %p %p %d, stub!\n", + handle, access, attr, process, id, ctx, teb, suspended ); + return STATUS_NOT_IMPLEMENTED; +} + +/*********************************************************************** + * NtCreateThreadEx (NTDLL.@) + */ +NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, + ULONG flags, ULONG_PTR zero_bits, SIZE_T stack_commit, + SIZE_T stack_reserve, PS_ATTRIBUTE_LIST *attr_list ) +{ + return create_thread( handle, access, attr, process, start, param, flags, + zero_bits, stack_commit, stack_reserve, attr_list ); +} + /*********************************************************************** * abort_thread -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9579
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/unix/thread.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index f13d999ec9e..e8d00dbfba9 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1339,7 +1339,8 @@ static NTSTATUS create_pthread( struct ntdll_thread_data *thread_data, TEB *teb static NTSTATUS create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, ULONG flags, ULONG_PTR zero_bits, SIZE_T stack_commit, - SIZE_T stack_reserve, PS_ATTRIBUTE_LIST *attr_list ) + SIZE_T stack_reserve, PS_ATTRIBUTE_LIST *attr_list, + NTSTATUS (*thread_create)( struct ntdll_thread_data *thread_data, TEB *teb ) ) { static const ULONG supported_flags = THREAD_CREATE_FLAGS_CREATE_SUSPENDED | THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH | THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER | THREAD_CREATE_FLAGS_SKIP_LOADER_INIT | @@ -1452,7 +1453,7 @@ static NTSTATUS create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIB thread_data->param = param; InterlockedIncrement( &nb_threads ); - if ((status = create_pthread( thread_data, teb ))) + if ((status = thread_create( thread_data, teb ))) { InterlockedDecrement( &nb_threads ); virtual_free_teb( teb ); @@ -1491,7 +1492,7 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT SIZE_T stack_reserve, PS_ATTRIBUTE_LIST *attr_list ) { return create_thread( handle, access, attr, process, start, param, flags, - zero_bits, stack_commit, stack_reserve, attr_list ); + zero_bits, stack_commit, stack_reserve, attr_list, create_pthread ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9579
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/unix/loader.c | 16 ++++++++++++++++ dlls/ntdll/unixlib.h | 1 + 2 files changed, 17 insertions(+) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index c9696fef115..48edd2e1844 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1006,6 +1006,20 @@ static NTSTATUS unwind_builtin_dll( void *args ) #endif /* SO_DLLS_SUPPORTED */ +/*********************************************************************** + * run_mac_cfrunloop + */ +static NTSTATUS run_mac_cfrunloop( void *args ) +{ +#ifdef __APPLE__ + CFRunLoopRun(); /* Should never return, except on error. */ + return STATUS_SUCCESS; +#else + return STATUS_NOT_IMPLEMENTED; +#endif +} + + static const unixlib_entry_t unix_call_funcs[] = { load_so_dll, @@ -1016,6 +1030,7 @@ static const unixlib_entry_t unix_call_funcs[] = unixcall_wine_server_handle_to_fd, unixcall_wine_spawnvp, system_time_precise, + run_mac_cfrunloop, }; @@ -1034,6 +1049,7 @@ const unixlib_entry_t unix_call_wow64_funcs[] = wow64_wine_server_handle_to_fd, wow64_wine_spawnvp, system_time_precise, + run_mac_cfrunloop, }; #endif /* _WIN64 */ diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 9cb444342fe..ef2f974f59a 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -76,6 +76,7 @@ enum ntdll_unix_funcs unix_wine_server_handle_to_fd, unix_wine_spawnvp, unix_system_time_precise, + unix_mac_run_cfrunloop, }; extern unixlib_handle_t __wine_unixlib_handle; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9579
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/loader.c | 20 ++++++++++++++++++++ dlls/ntdll/ntdll.spec | 1 + 2 files changed, 21 insertions(+) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index ac42ba7c24c..9420e550c2d 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -3405,6 +3405,26 @@ NTSTATUS WINAPI __wine_unix_spawnvp( char * const argv[], int wait ) } +/*********************************************************************** + * __wine_mac_run_cfrunloop + */ +NTSTATUS WINAPI __wine_mac_run_cfrunloop(void) +{ + static const WCHAR nameW[] = L"wine_mac_main_thread"; + THREAD_NAME_INFORMATION info; + NTSTATUS status; + + info.ThreadName.Length = info.ThreadName.MaximumLength = lstrlenW( nameW ) * sizeof(WCHAR); + info.ThreadName.Buffer = (WCHAR *)nameW; + NtSetInformationThread( GetCurrentThread(), ThreadNameInformation, &info, sizeof(info) ); + + status = WINE_UNIX_CALL( unix_mac_run_cfrunloop, NULL ); /* Should never return, except on error. */ + + ERR("macOS main thread crashed with status %lx, exiting\n", status); + for (;;) NtTerminateProcess( GetCurrentProcess(), status ); +} + + /*********************************************************************** * wine_server_call */ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 7d04a80b1eb..7d43c3919f9 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1749,6 +1749,7 @@ # Unix interface @ stdcall __wine_unix_spawnvp(long ptr) @ stdcall __wine_ctrl_routine(ptr) +@ stdcall __wine_mac_run_cfrunloop() @ extern -private __wine_syscall_dispatcher @ extern -private __wine_unix_call_dispatcher @ extern -private -arch=arm64ec __wine_unix_call_dispatcher_arm64ec -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9579
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/unix/loader.c | 2 ++ dlls/ntdll/unix/unix_private.h | 1 + 2 files changed, 3 insertions(+) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 48edd2e1844..4f400044e42 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -108,6 +108,7 @@ void *pKiUserEmulationDispatcher = NULL; void *pLdrInitializeThunk = NULL; void *pRtlUserThreadStart = NULL; void *p__wine_ctrl_routine = NULL; +void *p__wine_mac_run_cfrunloop = NULL; SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock = NULL; #ifdef __GNUC__ @@ -1521,6 +1522,7 @@ static void load_ntdll_functions( HMODULE module ) GET_FUNC( LdrSystemDllInitBlock ); GET_FUNC( RtlUserThreadStart ); GET_FUNC( __wine_ctrl_routine ); + GET_FUNC( __wine_mac_run_cfrunloop ); GET_FUNC( __wine_syscall_dispatcher ); GET_FUNC( __wine_unix_call_dispatcher ); GET_FUNC( __wine_unixlib_handle ); diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 8d77d726a33..df324a3b54a 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -170,6 +170,7 @@ extern void *pKiUserEmulationDispatcher; extern void *pLdrInitializeThunk; extern void *pRtlUserThreadStart; extern void *p__wine_ctrl_routine; +extern void *p__wine_mac_run_cfrunloop; extern SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock; struct _FILE_FS_DEVICE_INFORMATION; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9579
From: Brendan Shanks <bshanks@codeweavers.com> --- dlls/ntdll/unix/server.c | 5 +++ dlls/ntdll/unix/thread.c | 64 ++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/unix_private.h | 1 + 3 files changed, 70 insertions(+) diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 258a959de72..84f89367545 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -1751,6 +1751,11 @@ void server_init_process_done(void) thread_data->syscall_table = KeServiceDescriptorTable; thread_data->syscall_trace = TRACE_ON(syscall); +#ifdef __APPLE__ + /* This must run after signal_init_process() so the syscall dispatcher pointer is present at 0x7ffe1000 */ + transform_mac_main_thread(); +#endif + /* always send the native TEB */ if (!(teb = NtCurrentTeb64())) teb = NtCurrentTeb(); diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index e8d00dbfba9..0a862f33e90 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -63,6 +63,8 @@ #endif #ifdef __APPLE__ +#include <CoreFoundation/CoreFoundation.h> +#include <dispatch/dispatch.h> #include <mach/mach.h> #endif #ifdef __FreeBSD__ @@ -1471,6 +1473,7 @@ done: return status; } + /*********************************************************************** * NtCreateThread (NTDLL.@) */ @@ -2782,3 +2785,64 @@ NTSTATUS WINAPI NtWorkerFactoryWorkerReady( HANDLE handle ) return STATUS_NOT_IMPLEMENTED; } + + +#ifdef __APPLE__ +static dispatch_semaphore_t main_thread_transformed_semaphore; + +static void signal_semaphore_and_start_thread( TEB *teb ) +{ + dispatch_semaphore_signal( main_thread_transformed_semaphore ); + start_thread( teb ); +} + + +/*********************************************************************** + * run_on_mac_main_thread + */ +static NTSTATUS run_on_mac_main_thread( struct ntdll_thread_data *thread_data, TEB *teb ) +{ + CFRunLoopSourceContext source_context = { 0 }; + CFRunLoopSourceRef source; + + source_context.perform = (void (*)(void *))signal_semaphore_and_start_thread; + source_context.info = teb; + source = CFRunLoopSourceCreate( NULL, 0, &source_context ); + if (!source) + return STATUS_NO_MEMORY; + + CFRunLoopAddSource( CFRunLoopGetMain(), source, kCFRunLoopCommonModes ); + CFRunLoopSourceSignal( source ); + CFRunLoopWakeUp( CFRunLoopGetMain() ); + CFRelease( source ); + return STATUS_SUCCESS; +} + + +/*********************************************************************** + * transform_mac_main_thread + * + * Transform the process main thread into a Wine thread + */ +void transform_mac_main_thread( void ) +{ + NTSTATUS status; + HANDLE handle; + + main_thread_transformed_semaphore = dispatch_semaphore_create( 0 ); + + status = create_thread( &handle, THREAD_ALL_ACCESS, NULL, NtCurrentProcess(), + p__wine_mac_run_cfrunloop, NULL, + THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER | THREAD_CREATE_FLAGS_SKIP_LOADER_INIT, + 0, 0, 0, NULL, run_on_mac_main_thread ); + if (!status) + { + NtClose( handle ); + dispatch_semaphore_wait( main_thread_transformed_semaphore, DISPATCH_TIME_FOREVER ); + } + else + ERR("Failed to transform main thread: %x\n", status); + + dispatch_release( main_thread_transformed_semaphore ); +} +#endif diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index df324a3b54a..64ba7f68d6f 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -263,6 +263,7 @@ extern void set_process_instrumentation_callback( void *callback ); extern void *get_cpu_area( USHORT machine ); extern void set_thread_id( TEB *teb, DWORD pid, DWORD tid ); extern NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR limit, SIZE_T reserve_size, SIZE_T commit_size ); +extern void transform_mac_main_thread( void ); extern void DECLSPEC_NORETURN abort_thread( int status ); extern void DECLSPEC_NORETURN abort_process( int status ); extern void DECLSPEC_NORETURN exit_process( int status ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9579
That seems like a roundabout way of doing things. The reason we spawned a separate thread early was precisely to avoid having the main thread become a Wine thread. If we want that now, then we could simply run the process init on the main thread. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9579#note_128778
Wouldn't that conflict with Windows application main thread? As I understand it on macOS the main thread is the only one that can drive the GUI application, which pretty much means entering a macOS specific event loop (or calling it often enough), and that doesn't seem to very compatible with sharing execution with Windows main thread. The Windows main thread could also be spawned as a separate thread from it, but wouldn't that be more likely to break some possible assumptions about the TID of the Windows main thread vs its PID? Or is that not an issue for some reason? (Fwiw I think it would be nice to have this and I was investigating some way to implement in-process compositor with a dedicated thread. On wayland and macOS I was trying to merge this thread with their existing thread, and I ended up figuring that on macOS only the main thread can interact with GUI.) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9579#note_128967
The Windows main thread could also be spawned as a separate thread from it, but wouldn't that be more likely to break some possible assumptions about the TID of the Windows main thread vs its PID? Or is that not an issue for some reason?
It would need a mechanism to move the Windows TID to the new thread, but that shouldn't be too hard.
(Fwiw I think it would be nice to have this and I was investigating some way to implement in-process compositor with a dedicated thread. On wayland and macOS I was trying to merge this thread with their existing thread, and I ended up figuring that on macOS only the main thread can interact with GUI.)
Yes, hopefully we can have some generic mechanism to do everything in the same thread, so that we don't need to create a dozen extra threads for each process... -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9579#note_128968
The Windows main thread could also be spawned as a separate thread from it, but wouldn't that be more likely to break some possible assumptions about the TID of the Windows main thread vs its PID? Or is that not an issue for some reason?
It would need a mechanism to move the Windows TID to the new thread, but that shouldn't be too hard.
I'd have to double check, but I don't think Windows PID/TID even have that relationship. On modern Windows they seem to be more or less random. The more annoying part would be debugging. It's convenient (although, granted, already not always reliable) to see process 01c0 and know its first thread is probably 01c4, and vice versa. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9579#note_128983
The main thread needs to be running a CFRunLoop or NSRunLoop, but it's fine for it to be a Wine thread (i.e. have a TEB, and even have a roundtrip through PE code like this MR currently does). The PE roundtrip isn't mandatory, but does allow for crashes to be handled and means PE code is in the backtrace in case anticheats are looking for that. At least on macOS, there's other ways we could try to do the crash handling. I'll defer to Rémi's !10058 which is taking the non-PE route. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9579#note_129311
participants (5)
-
Alexandre Julliard (@julliard) -
Brendan Shanks -
Brendan Shanks (@bshanks) -
Elizabeth Figura (@zfigura) -
Rémi Bernon (@rbernon)