From: Brendan Shanks <bshanks@codeweavers.com> Based on a patch from Rémi Bernon. --- dlls/ntdll/unix/server.c | 1 + dlls/ntdll/unix/thread.c | 38 ++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/unix_private.h | 3 +++ 3 files changed, 42 insertions(+) diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 1629ee63e63..f084bfb2d7e 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -1754,6 +1754,7 @@ void server_init_process_done(void) #ifdef __APPLE__ send_server_task_port(); + convert_mac_main_thread(); #endif /* Install signal handlers; this cannot be done earlier, since we cannot diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 55e52af402a..a1279ff28c5 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -63,6 +63,7 @@ #endif #ifdef __APPLE__ +#include <CoreFoundation/CoreFoundation.h> #include <mach/mach.h> #endif #ifdef __FreeBSD__ @@ -1329,6 +1330,24 @@ static NTSTATUS spawn_thread( struct thread_data *data ) pthread_attr_t attr; NTSTATUS status = STATUS_SUCCESS; +#ifdef __APPLE__ + if (data->start == CFRunLoopRun) + { + CFRunLoopSourceContext context = { .perform = (void (*)(void *))server_init_thread, .info = data }; + CFRunLoopSourceRef source; + + if (!(source = CFRunLoopSourceCreate( NULL, 0, &context ))) return STATUS_NO_MEMORY; + + InterlockedIncrement( &nb_threads ); + CFRunLoopAddSource( CFRunLoopGetMain(), source, kCFRunLoopCommonModes ); + CFRunLoopSourceSignal( source ); + CFRunLoopWakeUp( CFRunLoopGetMain() ); + CFRelease( source ); + + return STATUS_SUCCESS; + } +#endif + pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset ); pthread_attr_init( &attr ); pthread_attr_setstack( &attr, get_kernel_stack( data ), kernel_stack_size ); @@ -1581,6 +1600,25 @@ void wait_suspend( CONTEXT *context ) } +#ifdef __APPLE__ +/********************************************************************** + * convert_mac_main_thread + * + * Convert the process main thread into a Wine system thread + */ +void convert_mac_main_thread( void ) +{ + NTSTATUS status; + HANDLE thread; + + if ((status = PsCreateSystemThread(&thread, THREAD_ALL_ACCESS, NULL, 0, NULL, (void *)CFRunLoopRun, NULL))) + ERR("Failed to spawn main thread, status %#x\n", status); + + NtClose(thread); +} +#endif + + /********************************************************************** * send_debug_event * diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index c8ca97d21a0..9bd3ec06edf 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -285,6 +285,9 @@ extern void DECLSPEC_NORETURN abort_thread( int status ); extern void DECLSPEC_NORETURN abort_process( int status ); extern void DECLSPEC_NORETURN exit_process( int status ); extern void wait_suspend( CONTEXT *context ); +#ifdef __APPLE__ +extern void convert_mac_main_thread( void ); +#endif extern NTSTATUS send_debug_event( struct thread_data *data, EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance, BOOL exception ); extern NTSTATUS set_thread_context( HANDLE handle, const void *context, BOOL *self, USHORT machine ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9579