Module: wine Branch: master Commit: 8891d6de48fdc43ef045fcc7470297952a97ed92 URL: http://source.winehq.org/git/wine.git/?a=commit;h=8891d6de48fdc43ef045fcc747...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Jan 18 12:23:04 2007 +0100
ntdll: Block async signals during process init and thread creation.
---
dlls/ntdll/loader.c | 19 +------------------ dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/server.c | 33 +++++++++++++++++++++++++++++++++ dlls/ntdll/thread.c | 13 ++++++++++++- 4 files changed, 47 insertions(+), 19 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 3e3bc05..7ff3ca1 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2139,24 +2139,7 @@ void WINAPI LdrInitializeThunk( ULONG un RemoveEntryList( &wm->ldr.InLoadOrderModuleList ); InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList );
- /* Install signal handlers; this cannot be done before, since we cannot - * send exceptions to the debugger before the create process event that - * is sent by REQ_INIT_PROCESS_DONE. - * We do need the handlers in place by the time the request is over, so - * we set them up here. If we segfault between here and the server call - * something is very wrong... */ - if (!SIGNAL_Init()) exit(1); - - /* Signal the parent process to continue */ - SERVER_START_REQ( init_process_done ) - { - req->module = peb->ImageBaseAddress; - req->entry = (char *)peb->ImageBaseAddress + nt->OptionalHeader.AddressOfEntryPoint; - req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI); - status = wine_server_call( req ); - } - SERVER_END_REQ; - + status = server_init_process_done(); if (status != STATUS_SUCCESS) goto error;
RtlEnterCriticalSection( &loader_section ); diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 725665d..4a8c474 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -58,6 +58,7 @@ extern void virtual_init_threading(void) /* server support */ extern abs_time_t server_start_time; extern void server_init_process(void); +extern NTSTATUS server_init_process_done(void); extern size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point ); extern void DECLSPEC_NORETURN server_protocol_error( const char *err, ... ); extern void DECLSPEC_NORETURN server_protocol_perror( const char *err ); diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index ded9f5b..ce0c3af 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -1018,6 +1018,7 @@ void server_init_process(void) sigaddset( &server_block_set, SIGUSR1 ); sigaddset( &server_block_set, SIGUSR2 ); sigaddset( &server_block_set, SIGCHLD ); + pthread_functions.sigprocmask( SIG_BLOCK, &server_block_set, NULL );
/* receive the first thread request fd on the main socket */ ntdll_get_thread_data()->request_fd = receive_fd( &dummy_handle ); @@ -1029,6 +1030,38 @@ void server_init_process(void)
/*********************************************************************** + * server_init_process_done + */ +NTSTATUS server_init_process_done(void) +{ + PEB *peb = NtCurrentTeb()->Peb; + IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); + NTSTATUS status; + + /* Install signal handlers; this cannot be done earlier, since we cannot + * send exceptions to the debugger before the create process event that + * is sent by REQ_INIT_PROCESS_DONE. + * We do need the handlers in place by the time the request is over, so + * we set them up here. If we segfault between here and the server call + * something is very wrong... */ + if (!SIGNAL_Init()) exit(1); + + /* Signal the parent process to continue */ + SERVER_START_REQ( init_process_done ) + { + req->module = peb->ImageBaseAddress; + req->entry = (char *)peb->ImageBaseAddress + nt->OptionalHeader.AddressOfEntryPoint; + req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI); + status = wine_server_call( req ); + } + SERVER_END_REQ; + + pthread_functions.sigprocmask( SIG_UNBLOCK, &server_block_set, NULL ); + return status; +} + + +/*********************************************************************** * server_init_thread * * Send an init thread request. Return 0 if OK. diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 4a82e43..356ba11 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -346,6 +346,8 @@ static void start_thread( struct wine_pt size = page_size; NtProtectVirtualMemory( NtCurrentProcess(), &teb->DeallocationStack, &size, PAGE_NOACCESS, NULL );
+ pthread_functions.sigprocmask( SIG_UNBLOCK, &server_block_set, NULL ); + RtlAcquirePebLock(); InsertHeadList( &tls_links, &teb->TlsLinks ); RtlReleasePebLock(); @@ -380,6 +382,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HAN PRTL_THREAD_START_ROUTINE start, void *param, HANDLE *handle_ptr, CLIENT_ID *id ) { + sigset_t sigset; struct ntdll_thread_data *thread_data; struct ntdll_thread_regs *thread_regs = NULL; struct startup_info *info = NULL; @@ -416,7 +419,13 @@ NTSTATUS WINAPI RtlCreateUserThread( HAN } SERVER_END_REQ;
- if (status) goto error; + if (status) + { + close( request_pipe[1] ); + return status; + } + + pthread_functions.sigprocmask( SIG_BLOCK, &server_block_set, &sigset );
addr = NULL; size = sigstack_total_size; @@ -469,6 +478,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HAN status = STATUS_NO_MEMORY; goto error; } + pthread_functions.sigprocmask( SIG_SETMASK, &sigset, NULL );
if (id) id->UniqueThread = (HANDLE)tid; if (handle_ptr) *handle_ptr = handle; @@ -484,6 +494,7 @@ error: NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE ); } if (handle) NtClose( handle ); + pthread_functions.sigprocmask( SIG_SETMASK, &sigset, NULL ); close( request_pipe[1] ); return status; }