From: Rémi Bernon rbernon@codeweavers.com
--- dlls/ntdll/unix/server.c | 5 +++++ dlls/ntdll/unix/thread.c | 19 ++++++++++++++++--- dlls/ntdll/unix/unix_private.h | 1 + dlls/ntdll/unix/virtual.c | 9 +++++---- server/inproc_sync.c | 17 ++++++++++++++--- server/object.h | 1 + server/protocol.def | 2 ++ server/thread.c | 15 +++++++++++++-- 8 files changed, 57 insertions(+), 12 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index d44b4b90f3d..2f1773c017f 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -1662,6 +1662,11 @@ size_t server_init_process(void) inproc_device_fd = wine_server_receive_fd( &handle ); assert( handle == reply->inproc_device ); } + if (reply->alert_handle) + { + data->alert_sync_fd = wine_server_receive_fd( &handle ); + assert( handle == reply->alert_handle ); + } } } SERVER_END_REQ; diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 65e7fbcb6bf..331a4eab08f 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1104,6 +1104,7 @@ static void contexts_from_server( CONTEXT *context, struct context_data server_c */ static DECLSPEC_NORETURN void pthread_exit_wrapper( int status ) { + close( ntdll_get_thread_data()->alert_sync_fd ); close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); @@ -1324,10 +1325,11 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT struct object_attributes *objattr; struct ntdll_thread_data *thread_data; DWORD tid = 0; - int request_pipe[2]; + int request_pipe[2], alert_sync_fd = -1; TEB *teb; WOW_TEB *wow_teb; unsigned int status; + obj_handle_t token;
if (flags & ~supported_flags) FIXME( "Unsupported flags %#x.\n", flags ); @@ -1377,6 +1379,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT
if (!access) access = THREAD_ALL_ACCESS;
+ server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + SERVER_START_REQ( new_thread ) { req->process = wine_server_obj_handle( process ); @@ -1384,8 +1388,13 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT req->flags = flags; req->request_fd = request_pipe[0]; wine_server_add_data( req, objattr, len ); - if (!(status = wine_server_call( req ))) + if (!(status = server_call_unlocked( req ))) { + if (reply->alert_handle) + { + alert_sync_fd = wine_server_receive_fd( &token ); + assert( token == reply->alert_handle ); + } *handle = wine_server_ptr_handle( reply->handle ); tid = reply->tid; } @@ -1393,6 +1402,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT } SERVER_END_REQ;
+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); + free( objattr ); if (status) { @@ -1417,7 +1428,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT if (wow_teb) wow_teb->SkipThreadAttach = teb->SkipThreadAttach;
thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; - thread_data->request_fd = request_pipe[1]; + thread_data->request_fd = request_pipe[1]; + thread_data->alert_sync_fd = alert_sync_fd; thread_data->start = start; thread_data->param = param;
@@ -1439,6 +1451,7 @@ done: if (status) { NtClose( *handle ); + close( alert_sync_fd ); close( request_pipe[1] ); return status; } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index f514f61dd60..b757fe5c3d1 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -108,6 +108,7 @@ struct ntdll_thread_data int request_fd; /* fd for sending server requests */ int reply_fd; /* fd for receiving server replies */ int wait_fd[2]; /* fd for sleeping server requests */ + int alert_sync_fd; /* inproc sync fd for user apc alerts */ BOOL allow_writes; /* ThreadAllowWrites flags */ pthread_t pthread_id; /* pthread thread id */ void *kernel_stack; /* stack for thread startup and kernel syscalls */ diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 994f76fb72a..a6854adfe36 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -4022,10 +4022,11 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; - thread_data->request_fd = -1; - thread_data->reply_fd = -1; - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; + thread_data->request_fd = -1; + thread_data->reply_fd = -1; + thread_data->wait_fd[0] = -1; + thread_data->wait_fd[1] = -1; + thread_data->alert_sync_fd = -1; list_add_head( &teb_list, &thread_data->entry ); return teb; } diff --git a/server/inproc_sync.c b/server/inproc_sync.c index 41a9c2770a7..f364129b35a 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -87,6 +87,12 @@ static const struct object_ops inproc_sync_ops = inproc_sync_destroy, /* destroy */ };
+int get_inproc_sync_fd( struct inproc_sync *sync ) +{ + if (!sync) return -1; + return sync->fd; +} + struct inproc_sync *create_inproc_internal_sync( int manual, int signaled ) { struct ntsync_event_args args = {.signaled = signaled, .manual = manual}; @@ -133,7 +139,7 @@ static void inproc_sync_destroy( struct object *obj ) close( sync->fd ); }
-static int get_inproc_sync_fd( struct object *obj, int *type ) +static int get_obj_inproc_sync( struct object *obj, int *type ) { struct object *sync; int fd = -1; @@ -160,6 +166,11 @@ int get_inproc_device_fd(void) return -1; }
+int get_inproc_sync_fd( struct inproc_sync *sync ) +{ + return -1; +} + struct inproc_sync *create_inproc_internal_sync( int manual, int signaled ) { return NULL; @@ -173,7 +184,7 @@ void reset_inproc_sync( struct inproc_sync *sync ) { }
-static int get_inproc_sync_fd( struct object *obj, int *type ) +static int get_obj_inproc_sync( struct object *obj, int *type ) { return -1; } @@ -189,7 +200,7 @@ DECL_HANDLER(get_inproc_sync_fd)
reply->access = get_handle_access( current->process, req->handle );
- if ((fd = get_inproc_sync_fd( obj, &reply->type )) < 0) set_error( STATUS_NOT_IMPLEMENTED ); + if ((fd = get_obj_inproc_sync( obj, &reply->type )) < 0) set_error( STATUS_NOT_IMPLEMENTED ); else send_client_fd( current->process, fd, req->handle );
release_object( obj ); diff --git a/server/object.h b/server/object.h index 203734a565f..995041c2dcf 100644 --- a/server/object.h +++ b/server/object.h @@ -244,6 +244,7 @@ extern void abandon_mutexes( struct thread *thread );
struct inproc_sync; extern int get_inproc_device_fd(void); +extern int get_inproc_sync_fd( struct inproc_sync *sync ); extern struct inproc_sync *create_inproc_internal_sync( int manual, int signaled ); extern void signal_inproc_sync( struct inproc_sync *sync ); extern void reset_inproc_sync( struct inproc_sync *sync ); diff --git a/server/protocol.def b/server/protocol.def index 0c8be12314a..262efd1d56e 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1102,6 +1102,7 @@ typedef volatile struct @REPLY thread_id_t tid; /* thread id */ obj_handle_t handle; /* thread handle (in the current process) */ + obj_handle_t alert_handle; /* alert fd is in flight with this handle */ @END
@@ -1137,6 +1138,7 @@ typedef volatile struct timeout_t server_start; /* server start time */ unsigned int session_id; /* process session id */ obj_handle_t inproc_device;/* inproc device fd in flight with this handle */ + obj_handle_t alert_handle; /* alert fd is in flight with this handle */ data_size_t info_size; /* total size of startup info */ VARARG(machines,ushorts); /* array of supported machines */ @END diff --git a/server/thread.c b/server/thread.c index 853aff4cc84..72817681e25 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1631,7 +1631,7 @@ DECL_HANDLER(new_thread) struct unicode_str name; const struct security_descriptor *sd; const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); - int request_fd = thread_get_inflight_fd( current, req->request_fd ); + int fd, request_fd = thread_get_inflight_fd( current, req->request_fd );
if (!(process = get_process_from_handle( req->process, 0 ))) { @@ -1676,6 +1676,12 @@ DECL_HANDLER(new_thread) if ((reply->handle = alloc_handle_no_access_check( current->process, thread, req->access, objattr->attributes ))) { + /* first thread fd will be sent in init_first_thread */ + if (request_fd != -1 && (fd = get_inproc_sync_fd( thread->alert_sync )) >= 0) + { + reply->alert_handle = get_thread_id( thread ) | 1; /* arbitrary token */ + send_client_fd( thread->process, fd, reply->alert_handle ); + } /* thread object will be released when the thread gets killed */ goto done; } @@ -1746,9 +1752,14 @@ DECL_HANDLER(init_first_thread)
if ((fd = get_inproc_device_fd()) >= 0) { - reply->inproc_device = get_process_id( process ) | 1; + reply->inproc_device = get_process_id( process ) | 1; /* arbitrary token */ send_client_fd( process, fd, reply->inproc_device ); } + if ((fd = get_inproc_sync_fd( current->alert_sync )) >= 0) + { + reply->alert_handle = get_thread_id( current ) | 1; /* arbitrary token */ + send_client_fd( process, fd, reply->alert_handle ); + } }
/* initialize a new thread */