server: Add a separate request to initialize the first thread of a process.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
123023eac7
commit
44699c324f
|
@ -1618,7 +1618,6 @@ static struct unix_funcs unix_funcs =
|
|||
*/
|
||||
static void start_main_thread(void)
|
||||
{
|
||||
BOOL suspend;
|
||||
NTSTATUS status;
|
||||
TEB *teb = virtual_alloc_first_teb();
|
||||
|
||||
|
@ -1626,8 +1625,7 @@ static void start_main_thread(void)
|
|||
signal_alloc_thread( teb );
|
||||
signal_init_thread( teb );
|
||||
dbg_init();
|
||||
server_init_process();
|
||||
startup_info_size = server_init_thread( teb->Peb, &suspend );
|
||||
startup_info_size = server_init_process();
|
||||
virtual_map_user_shared_data();
|
||||
init_cpu_info();
|
||||
init_files();
|
||||
|
|
|
@ -1412,15 +1412,62 @@ static int get_unix_tid(void)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* init_thread_pipe
|
||||
*
|
||||
* Create the server->client communication pipe.
|
||||
*/
|
||||
static int init_thread_pipe(void)
|
||||
{
|
||||
int reply_pipe[2];
|
||||
stack_t ss;
|
||||
|
||||
ss.ss_sp = get_signal_stack();
|
||||
ss.ss_size = signal_stack_size;
|
||||
ss.ss_flags = 0;
|
||||
sigaltstack( &ss, NULL );
|
||||
|
||||
if (server_pipe( reply_pipe ) == -1) server_protocol_perror( "pipe" );
|
||||
if (server_pipe( ntdll_get_thread_data()->wait_fd ) == -1) server_protocol_perror( "pipe" );
|
||||
wine_server_send_fd( reply_pipe[1] );
|
||||
wine_server_send_fd( ntdll_get_thread_data()->wait_fd[1] );
|
||||
ntdll_get_thread_data()->reply_fd = reply_pipe[0];
|
||||
return reply_pipe[1];
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* init_teb64
|
||||
*
|
||||
* Initialize the 64-bit part of the TEB for WoW64 threads.
|
||||
*/
|
||||
static void init_teb64( TEB *teb )
|
||||
{
|
||||
#ifndef _WIN64
|
||||
TEB64 *teb64 = (TEB64 *)((char *)teb - teb_offset);
|
||||
|
||||
if (!is_wow64) return;
|
||||
teb->GdiBatchCount = PtrToUlong( teb64 );
|
||||
teb->WowTebOffset = -teb_offset;
|
||||
teb64->ClientId.UniqueProcess = PtrToUlong( teb->ClientId.UniqueProcess );
|
||||
teb64->ClientId.UniqueThread = PtrToUlong( teb->ClientId.UniqueThread );
|
||||
#endif
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* server_init_process
|
||||
*
|
||||
* Start the server and create the initial socket pair.
|
||||
*/
|
||||
void server_init_process(void)
|
||||
size_t server_init_process(void)
|
||||
{
|
||||
obj_handle_t version;
|
||||
static const char *cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" };
|
||||
const char *arch = getenv( "WINEARCH" );
|
||||
const char *env_socket = getenv( "WINESERVERSOCKET" );
|
||||
obj_handle_t version;
|
||||
int ret, reply_pipe;
|
||||
struct sigaction sig_act;
|
||||
size_t info_size;
|
||||
|
||||
server_pid = -1;
|
||||
if (env_socket)
|
||||
|
@ -1473,6 +1520,60 @@ void server_init_process(void)
|
|||
/* work around Ubuntu's ptrace breakage */
|
||||
if (server_pid != -1) prctl( 0x59616d61 /* PR_SET_PTRACER */, server_pid );
|
||||
#endif
|
||||
|
||||
/* ignore SIGPIPE so that we get an EPIPE error instead */
|
||||
sig_act.sa_handler = SIG_IGN;
|
||||
sig_act.sa_flags = 0;
|
||||
sigemptyset( &sig_act.sa_mask );
|
||||
sigaction( SIGPIPE, &sig_act, NULL );
|
||||
|
||||
reply_pipe = init_thread_pipe();
|
||||
|
||||
SERVER_START_REQ( init_first_thread )
|
||||
{
|
||||
req->unix_pid = getpid();
|
||||
req->unix_tid = get_unix_tid();
|
||||
req->teb = wine_server_client_ptr( NtCurrentTeb() );
|
||||
req->peb = wine_server_client_ptr( NtCurrentTeb()->Peb );
|
||||
req->reply_fd = reply_pipe;
|
||||
req->wait_fd = ntdll_get_thread_data()->wait_fd[1];
|
||||
req->debug_level = (TRACE_ON(server) != 0);
|
||||
req->cpu = client_cpu;
|
||||
ret = wine_server_call( req );
|
||||
NtCurrentTeb()->ClientId.UniqueProcess = ULongToHandle(reply->pid);
|
||||
NtCurrentTeb()->ClientId.UniqueThread = ULongToHandle(reply->tid);
|
||||
info_size = reply->info_size;
|
||||
server_start_time = reply->server_start;
|
||||
server_cpus = reply->all_cpus;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
close( reply_pipe );
|
||||
|
||||
#ifndef _WIN64
|
||||
is_wow64 = (server_cpus & ((1 << CPU_x86_64) | (1 << CPU_ARM64))) != 0;
|
||||
init_teb64( NtCurrentTeb() );
|
||||
#endif
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case STATUS_SUCCESS:
|
||||
if (arch)
|
||||
{
|
||||
if (!strcmp( arch, "win32" ) && (is_win64 || is_wow64))
|
||||
fatal_error( "WINEARCH set to win32 but '%s' is a 64-bit installation.\n", config_dir );
|
||||
if (!strcmp( arch, "win64" ) && !is_win64 && !is_wow64)
|
||||
fatal_error( "WINEARCH set to win64 but '%s' is a 32-bit installation.\n", config_dir );
|
||||
}
|
||||
return info_size;
|
||||
case STATUS_INVALID_IMAGE_WIN_64:
|
||||
fatal_error( "'%s' is a 32-bit installation, it cannot support 64-bit applications.\n", config_dir );
|
||||
case STATUS_NOT_SUPPORTED:
|
||||
fatal_error( "'%s' is a 64-bit installation, it cannot be used with a 32-bit wineserver.\n", config_dir );
|
||||
case STATUS_INVALID_IMAGE_FORMAT:
|
||||
fatal_error( "wineserver doesn't support the %s architecture\n", cpu_names[client_cpu] );
|
||||
default:
|
||||
server_protocol_error( "init_first_thread failed with status %x\n", ret );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1530,88 +1631,25 @@ void server_init_process_done(void)
|
|||
*
|
||||
* Send an init thread request.
|
||||
*/
|
||||
size_t server_init_thread( void *entry_point, BOOL *suspend )
|
||||
void server_init_thread( void *entry_point, BOOL *suspend )
|
||||
{
|
||||
static const char *cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" };
|
||||
const char *arch = getenv( "WINEARCH" );
|
||||
int ret;
|
||||
int reply_pipe[2];
|
||||
struct sigaction sig_act;
|
||||
stack_t ss;
|
||||
size_t info_size;
|
||||
|
||||
/* ignore SIGPIPE so that we get an EPIPE error instead */
|
||||
sig_act.sa_handler = SIG_IGN;
|
||||
sig_act.sa_flags = 0;
|
||||
sigemptyset( &sig_act.sa_mask );
|
||||
sigaction( SIGPIPE, &sig_act, NULL );
|
||||
|
||||
ss.ss_sp = get_signal_stack();
|
||||
ss.ss_size = signal_stack_size;
|
||||
ss.ss_flags = 0;
|
||||
sigaltstack( &ss, NULL );
|
||||
|
||||
/* create the server->client communication pipes */
|
||||
if (server_pipe( reply_pipe ) == -1) server_protocol_perror( "pipe" );
|
||||
if (server_pipe( ntdll_get_thread_data()->wait_fd ) == -1) server_protocol_perror( "pipe" );
|
||||
wine_server_send_fd( reply_pipe[1] );
|
||||
wine_server_send_fd( ntdll_get_thread_data()->wait_fd[1] );
|
||||
ntdll_get_thread_data()->reply_fd = reply_pipe[0];
|
||||
close( reply_pipe[1] );
|
||||
int reply_pipe = init_thread_pipe();
|
||||
|
||||
SERVER_START_REQ( init_thread )
|
||||
{
|
||||
req->unix_pid = getpid();
|
||||
req->unix_tid = get_unix_tid();
|
||||
req->teb = wine_server_client_ptr( NtCurrentTeb() );
|
||||
req->entry = wine_server_client_ptr( entry_point );
|
||||
req->reply_fd = reply_pipe[1];
|
||||
req->wait_fd = ntdll_get_thread_data()->wait_fd[1];
|
||||
req->debug_level = (TRACE_ON(server) != 0);
|
||||
req->cpu = client_cpu;
|
||||
ret = wine_server_call( req );
|
||||
req->unix_tid = get_unix_tid();
|
||||
req->teb = wine_server_client_ptr( NtCurrentTeb() );
|
||||
req->entry = wine_server_client_ptr( entry_point );
|
||||
req->reply_fd = reply_pipe;
|
||||
req->wait_fd = ntdll_get_thread_data()->wait_fd[1];
|
||||
wine_server_call( req );
|
||||
*suspend = reply->suspend;
|
||||
NtCurrentTeb()->ClientId.UniqueProcess = ULongToHandle(reply->pid);
|
||||
NtCurrentTeb()->ClientId.UniqueThread = ULongToHandle(reply->tid);
|
||||
info_size = reply->info_size;
|
||||
server_start_time = reply->server_start;
|
||||
server_cpus = reply->all_cpus;
|
||||
*suspend = reply->suspend;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
#ifndef _WIN64
|
||||
is_wow64 = (server_cpus & ((1 << CPU_x86_64) | (1 << CPU_ARM64))) != 0;
|
||||
if (is_wow64)
|
||||
{
|
||||
TEB64 *teb64 = (TEB64 *)((char *)NtCurrentTeb() - teb_offset);
|
||||
|
||||
NtCurrentTeb()->GdiBatchCount = PtrToUlong( teb64 );
|
||||
NtCurrentTeb()->WowTebOffset = -teb_offset;
|
||||
teb64->ClientId.UniqueProcess = PtrToUlong( NtCurrentTeb()->ClientId.UniqueProcess );
|
||||
teb64->ClientId.UniqueThread = PtrToUlong( NtCurrentTeb()->ClientId.UniqueThread );
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case STATUS_SUCCESS:
|
||||
if (arch)
|
||||
{
|
||||
if (!strcmp( arch, "win32" ) && (is_win64 || is_wow64))
|
||||
fatal_error( "WINEARCH set to win32 but '%s' is a 64-bit installation.\n", config_dir );
|
||||
if (!strcmp( arch, "win64" ) && !is_win64 && !is_wow64)
|
||||
fatal_error( "WINEARCH set to win64 but '%s' is a 32-bit installation.\n", config_dir );
|
||||
}
|
||||
return info_size;
|
||||
case STATUS_INVALID_IMAGE_WIN_64:
|
||||
fatal_error( "'%s' is a 32-bit installation, it cannot support 64-bit applications.\n", config_dir );
|
||||
case STATUS_NOT_SUPPORTED:
|
||||
fatal_error( "'%s' is a 64-bit installation, it cannot be used with a 32-bit wineserver.\n", config_dir );
|
||||
case STATUS_INVALID_IMAGE_FORMAT:
|
||||
fatal_error( "wineserver doesn't support the %s architecture\n", cpu_names[client_cpu] );
|
||||
default:
|
||||
server_protocol_error( "init_thread failed with status %x\n", ret );
|
||||
}
|
||||
close( reply_pipe );
|
||||
init_teb64( NtCurrentTeb() );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -157,9 +157,9 @@ extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *
|
|||
apc_result_t *result ) DECLSPEC_HIDDEN;
|
||||
extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
|
||||
int *needs_close, enum server_fd_type *type, unsigned int *options ) DECLSPEC_HIDDEN;
|
||||
extern void server_init_process(void) DECLSPEC_HIDDEN;
|
||||
extern size_t server_init_process(void) DECLSPEC_HIDDEN;
|
||||
extern void server_init_process_done(void) DECLSPEC_HIDDEN;
|
||||
extern size_t server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN;
|
||||
extern void server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN;
|
||||
extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -893,29 +893,47 @@ struct init_process_done_reply
|
|||
|
||||
|
||||
|
||||
struct init_thread_request
|
||||
struct init_first_thread_request
|
||||
{
|
||||
struct request_header __header;
|
||||
int unix_pid;
|
||||
int unix_tid;
|
||||
int debug_level;
|
||||
client_ptr_t teb;
|
||||
client_ptr_t entry;
|
||||
client_ptr_t peb;
|
||||
int reply_fd;
|
||||
int wait_fd;
|
||||
client_cpu_t cpu;
|
||||
char __pad_52[4];
|
||||
};
|
||||
struct init_thread_reply
|
||||
struct init_first_thread_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
process_id_t pid;
|
||||
thread_id_t tid;
|
||||
timeout_t server_start;
|
||||
data_size_t info_size;
|
||||
int version;
|
||||
unsigned int all_cpus;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct init_thread_request
|
||||
{
|
||||
struct request_header __header;
|
||||
int unix_tid;
|
||||
int reply_fd;
|
||||
int wait_fd;
|
||||
client_ptr_t teb;
|
||||
client_ptr_t entry;
|
||||
};
|
||||
struct init_thread_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
process_id_t pid;
|
||||
thread_id_t tid;
|
||||
int suspend;
|
||||
char __pad_20[4];
|
||||
};
|
||||
|
||||
|
||||
|
@ -5373,6 +5391,7 @@ enum request
|
|||
REQ_new_thread,
|
||||
REQ_get_startup_info,
|
||||
REQ_init_process_done,
|
||||
REQ_init_first_thread,
|
||||
REQ_init_thread,
|
||||
REQ_terminate_process,
|
||||
REQ_terminate_thread,
|
||||
|
@ -5655,6 +5674,7 @@ union generic_request
|
|||
struct new_thread_request new_thread_request;
|
||||
struct get_startup_info_request get_startup_info_request;
|
||||
struct init_process_done_request init_process_done_request;
|
||||
struct init_first_thread_request init_first_thread_request;
|
||||
struct init_thread_request init_thread_request;
|
||||
struct terminate_process_request terminate_process_request;
|
||||
struct terminate_thread_request terminate_thread_request;
|
||||
|
@ -5935,6 +5955,7 @@ union generic_reply
|
|||
struct new_thread_reply new_thread_reply;
|
||||
struct get_startup_info_reply get_startup_info_reply;
|
||||
struct init_process_done_reply init_process_done_reply;
|
||||
struct init_first_thread_reply init_first_thread_reply;
|
||||
struct init_thread_reply init_thread_reply;
|
||||
struct terminate_process_reply terminate_process_reply;
|
||||
struct terminate_thread_reply terminate_thread_reply;
|
||||
|
@ -6208,7 +6229,7 @@ union generic_reply
|
|||
|
||||
/* ### protocol_version begin ### */
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 662
|
||||
#define SERVER_PROTOCOL_VERSION 663
|
||||
|
||||
/* ### protocol_version end ### */
|
||||
|
||||
|
|
|
@ -607,10 +607,9 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize the current process and fill in the request */
|
||||
data_size_t init_process( struct thread *thread )
|
||||
/* get the process data size */
|
||||
data_size_t get_process_startup_info_size( struct process *process )
|
||||
{
|
||||
struct process *process = thread->process;
|
||||
struct startup_info *info = process->startup_info;
|
||||
|
||||
if (!info) return 0;
|
||||
|
|
|
@ -108,7 +108,7 @@ extern void *get_ptid_entry( unsigned int id );
|
|||
extern struct process *create_process( int fd, struct process *parent, int inherit_all, const startup_info_t *info,
|
||||
const struct security_descriptor *sd, const obj_handle_t *handles,
|
||||
unsigned int handle_count, struct token *token );
|
||||
extern data_size_t init_process( struct thread *thread );
|
||||
extern data_size_t get_process_startup_info_size( struct process *process );
|
||||
extern struct thread *get_process_first_thread( struct process *process );
|
||||
extern struct process *get_process_from_id( process_id_t id );
|
||||
extern struct process *get_process_from_handle( obj_handle_t handle, unsigned int access );
|
||||
|
|
|
@ -870,13 +870,13 @@ typedef struct
|
|||
@END
|
||||
|
||||
|
||||
/* Initialize a thread; called from the child after fork()/clone() */
|
||||
@REQ(init_thread)
|
||||
int unix_pid; /* Unix pid of new thread */
|
||||
/* Initialize the first thread of a new process */
|
||||
@REQ(init_first_thread)
|
||||
int unix_pid; /* Unix pid of new process */
|
||||
int unix_tid; /* Unix tid of new thread */
|
||||
int debug_level; /* new debug level */
|
||||
client_ptr_t teb; /* TEB of new thread (in thread address space) */
|
||||
client_ptr_t entry; /* entry point or PEB if initial thread (in thread address space) */
|
||||
client_ptr_t teb; /* TEB of new thread (in process address space) */
|
||||
client_ptr_t peb; /* PEB of new process (in process address space) */
|
||||
int reply_fd; /* fd for reply pipe */
|
||||
int wait_fd; /* fd for blocking calls pipe */
|
||||
client_cpu_t cpu; /* CPU that this thread is running on */
|
||||
|
@ -885,8 +885,20 @@ typedef struct
|
|||
thread_id_t tid; /* thread id of the new thread */
|
||||
timeout_t server_start; /* server start time */
|
||||
data_size_t info_size; /* total size of startup info */
|
||||
int version; /* protocol version */
|
||||
unsigned int all_cpus; /* bitset of supported CPUs */
|
||||
@END
|
||||
|
||||
|
||||
/* Initialize a new thread; called from the child after pthread_create() */
|
||||
@REQ(init_thread)
|
||||
int unix_tid; /* Unix tid of new thread */
|
||||
int reply_fd; /* fd for reply pipe */
|
||||
int wait_fd; /* fd for blocking calls pipe */
|
||||
client_ptr_t teb; /* TEB of new thread (in thread address space) */
|
||||
client_ptr_t entry; /* entry point (in thread address space) */
|
||||
@REPLY
|
||||
process_id_t pid; /* process id of the new thread's process */
|
||||
thread_id_t tid; /* thread id of the new thread */
|
||||
int suspend; /* is thread suspended? */
|
||||
@END
|
||||
|
||||
|
|
|
@ -125,6 +125,7 @@ DECL_HANDLER(get_new_process_info);
|
|||
DECL_HANDLER(new_thread);
|
||||
DECL_HANDLER(get_startup_info);
|
||||
DECL_HANDLER(init_process_done);
|
||||
DECL_HANDLER(init_first_thread);
|
||||
DECL_HANDLER(init_thread);
|
||||
DECL_HANDLER(terminate_process);
|
||||
DECL_HANDLER(terminate_thread);
|
||||
|
@ -406,6 +407,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_new_thread,
|
||||
(req_handler)req_get_startup_info,
|
||||
(req_handler)req_init_process_done,
|
||||
(req_handler)req_init_first_thread,
|
||||
(req_handler)req_init_thread,
|
||||
(req_handler)req_terminate_process,
|
||||
(req_handler)req_terminate_thread,
|
||||
|
@ -748,23 +750,31 @@ C_ASSERT( FIELD_OFFSET(struct init_process_done_request, entry) == 32 );
|
|||
C_ASSERT( sizeof(struct init_process_done_request) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_process_done_reply, suspend) == 8 );
|
||||
C_ASSERT( sizeof(struct init_process_done_reply) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_pid) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_tid) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, debug_level) == 20 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, unix_pid) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, unix_tid) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, debug_level) == 20 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, teb) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, peb) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, reply_fd) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, wait_fd) == 44 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_request, cpu) == 48 );
|
||||
C_ASSERT( sizeof(struct init_first_thread_request) == 56 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, pid) == 8 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, tid) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, server_start) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, info_size) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_first_thread_reply, all_cpus) == 28 );
|
||||
C_ASSERT( sizeof(struct init_first_thread_reply) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, unix_tid) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, reply_fd) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, wait_fd) == 20 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, teb) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, entry) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, reply_fd) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, wait_fd) == 44 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_request, cpu) == 48 );
|
||||
C_ASSERT( sizeof(struct init_thread_request) == 56 );
|
||||
C_ASSERT( sizeof(struct init_thread_request) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, pid) == 8 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, tid) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, server_start) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, info_size) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, version) == 28 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, all_cpus) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, suspend) == 36 );
|
||||
C_ASSERT( sizeof(struct init_thread_reply) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct init_thread_reply, suspend) == 16 );
|
||||
C_ASSERT( sizeof(struct init_thread_reply) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct terminate_process_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct terminate_process_request, exit_code) == 16 );
|
||||
C_ASSERT( sizeof(struct terminate_process_request) == 24 );
|
||||
|
|
111
server/thread.c
111
server/thread.c
|
@ -1384,24 +1384,20 @@ done:
|
|||
release_object( process );
|
||||
}
|
||||
|
||||
/* initialize a new thread */
|
||||
DECL_HANDLER(init_thread)
|
||||
static int init_thread( struct thread *thread, int reply_fd, int wait_fd )
|
||||
{
|
||||
struct process *process = current->process;
|
||||
int wait_fd, reply_fd;
|
||||
|
||||
if ((reply_fd = thread_get_inflight_fd( current, req->reply_fd )) == -1)
|
||||
if ((reply_fd = thread_get_inflight_fd( thread, reply_fd )) == -1)
|
||||
{
|
||||
set_error( STATUS_TOO_MANY_OPENED_FILES );
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if ((wait_fd = thread_get_inflight_fd( current, req->wait_fd )) == -1)
|
||||
if ((wait_fd = thread_get_inflight_fd( thread, wait_fd )) == -1)
|
||||
{
|
||||
set_error( STATUS_TOO_MANY_OPENED_FILES );
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (current->reply_fd) /* already initialised */
|
||||
if (thread->reply_fd) /* already initialised */
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
goto error;
|
||||
|
@ -1409,9 +1405,55 @@ DECL_HANDLER(init_thread)
|
|||
|
||||
if (fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1) goto error;
|
||||
|
||||
current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, ¤t->obj, 0 );
|
||||
current->wait_fd = create_anonymous_fd( &thread_fd_ops, wait_fd, ¤t->obj, 0 );
|
||||
if (!current->reply_fd || !current->wait_fd) return;
|
||||
thread->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, &thread->obj, 0 );
|
||||
thread->wait_fd = create_anonymous_fd( &thread_fd_ops, wait_fd, &thread->obj, 0 );
|
||||
return thread->reply_fd && thread->wait_fd;
|
||||
|
||||
error:
|
||||
if (reply_fd != -1) close( reply_fd );
|
||||
if (wait_fd != -1) close( wait_fd );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* initialize the first thread of a new process */
|
||||
DECL_HANDLER(init_first_thread)
|
||||
{
|
||||
struct process *process = current->process;
|
||||
|
||||
if (!init_thread( current, req->reply_fd, req->wait_fd )) return;
|
||||
|
||||
if (!is_valid_address(req->teb) || !is_valid_address(req->peb))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_cpu_supported( req->cpu )) return;
|
||||
|
||||
current->unix_pid = process->unix_pid = req->unix_pid;
|
||||
current->unix_tid = req->unix_tid;
|
||||
current->teb = req->teb;
|
||||
process->peb = req->peb;
|
||||
process->cpu = req->cpu;
|
||||
|
||||
if (!process->parent_id)
|
||||
process->affinity = current->affinity = get_thread_affinity( current );
|
||||
else
|
||||
set_thread_affinity( current, current->affinity );
|
||||
|
||||
debug_level = max( debug_level, req->debug_level );
|
||||
|
||||
reply->pid = get_process_id( process );
|
||||
reply->tid = get_thread_id( current );
|
||||
reply->info_size = get_process_startup_info_size( process );
|
||||
reply->server_start = server_start_time;
|
||||
reply->all_cpus = supported_cpus & get_prefix_cpu_mask();
|
||||
}
|
||||
|
||||
/* initialize a new thread */
|
||||
DECL_HANDLER(init_thread)
|
||||
{
|
||||
if (!init_thread( current, req->reply_fd, req->wait_fd )) return;
|
||||
|
||||
if (!is_valid_address(req->teb))
|
||||
{
|
||||
|
@ -1419,49 +1461,18 @@ DECL_HANDLER(init_thread)
|
|||
return;
|
||||
}
|
||||
|
||||
current->unix_pid = req->unix_pid;
|
||||
current->unix_pid = current->process->unix_pid;
|
||||
current->unix_tid = req->unix_tid;
|
||||
current->teb = req->teb;
|
||||
current->entry_point = process->peb ? req->entry : 0;
|
||||
current->entry_point = req->entry;
|
||||
|
||||
if (!process->peb) /* first thread, initialize the process too */
|
||||
{
|
||||
if (!is_cpu_supported( req->cpu )) return;
|
||||
process->unix_pid = current->unix_pid;
|
||||
process->peb = req->entry;
|
||||
process->cpu = req->cpu;
|
||||
reply->info_size = init_process( current );
|
||||
if (!process->parent_id)
|
||||
process->affinity = current->affinity = get_thread_affinity( current );
|
||||
else
|
||||
set_thread_affinity( current, current->affinity );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (req->cpu != process->cpu)
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
if (process->unix_pid != current->unix_pid)
|
||||
process->unix_pid = -1; /* can happen with linuxthreads */
|
||||
init_thread_context( current );
|
||||
generate_debug_event( current, DbgCreateThreadStateChange, &req->entry );
|
||||
set_thread_affinity( current, current->affinity );
|
||||
}
|
||||
debug_level = max( debug_level, req->debug_level );
|
||||
init_thread_context( current );
|
||||
generate_debug_event( current, DbgCreateThreadStateChange, &req->entry );
|
||||
set_thread_affinity( current, current->affinity );
|
||||
|
||||
reply->pid = get_process_id( process );
|
||||
reply->pid = get_process_id( current->process );
|
||||
reply->tid = get_thread_id( current );
|
||||
reply->version = SERVER_PROTOCOL_VERSION;
|
||||
reply->server_start = server_start_time;
|
||||
reply->all_cpus = supported_cpus & get_prefix_cpu_mask();
|
||||
reply->suspend = (current->suspend || process->suspend || current->context != NULL);
|
||||
return;
|
||||
|
||||
error:
|
||||
if (reply_fd != -1) close( reply_fd );
|
||||
if (wait_fd != -1) close( wait_fd );
|
||||
reply->suspend = (current->suspend || current->process->suspend || current->context != NULL);
|
||||
}
|
||||
|
||||
/* terminate a thread */
|
||||
|
|
|
@ -1392,26 +1392,40 @@ static void dump_init_process_done_reply( const struct init_process_done_reply *
|
|||
fprintf( stderr, " suspend=%d", req->suspend );
|
||||
}
|
||||
|
||||
static void dump_init_thread_request( const struct init_thread_request *req )
|
||||
static void dump_init_first_thread_request( const struct init_first_thread_request *req )
|
||||
{
|
||||
fprintf( stderr, " unix_pid=%d", req->unix_pid );
|
||||
fprintf( stderr, ", unix_tid=%d", req->unix_tid );
|
||||
fprintf( stderr, ", debug_level=%d", req->debug_level );
|
||||
dump_uint64( ", teb=", &req->teb );
|
||||
dump_uint64( ", entry=", &req->entry );
|
||||
dump_uint64( ", peb=", &req->peb );
|
||||
fprintf( stderr, ", reply_fd=%d", req->reply_fd );
|
||||
fprintf( stderr, ", wait_fd=%d", req->wait_fd );
|
||||
dump_client_cpu( ", cpu=", &req->cpu );
|
||||
}
|
||||
|
||||
static void dump_init_first_thread_reply( const struct init_first_thread_reply *req )
|
||||
{
|
||||
fprintf( stderr, " pid=%04x", req->pid );
|
||||
fprintf( stderr, ", tid=%04x", req->tid );
|
||||
dump_timeout( ", server_start=", &req->server_start );
|
||||
fprintf( stderr, ", info_size=%u", req->info_size );
|
||||
fprintf( stderr, ", all_cpus=%08x", req->all_cpus );
|
||||
}
|
||||
|
||||
static void dump_init_thread_request( const struct init_thread_request *req )
|
||||
{
|
||||
fprintf( stderr, " unix_tid=%d", req->unix_tid );
|
||||
fprintf( stderr, ", reply_fd=%d", req->reply_fd );
|
||||
fprintf( stderr, ", wait_fd=%d", req->wait_fd );
|
||||
dump_uint64( ", teb=", &req->teb );
|
||||
dump_uint64( ", entry=", &req->entry );
|
||||
}
|
||||
|
||||
static void dump_init_thread_reply( const struct init_thread_reply *req )
|
||||
{
|
||||
fprintf( stderr, " pid=%04x", req->pid );
|
||||
fprintf( stderr, ", tid=%04x", req->tid );
|
||||
dump_timeout( ", server_start=", &req->server_start );
|
||||
fprintf( stderr, ", info_size=%u", req->info_size );
|
||||
fprintf( stderr, ", version=%d", req->version );
|
||||
fprintf( stderr, ", all_cpus=%08x", req->all_cpus );
|
||||
fprintf( stderr, ", suspend=%d", req->suspend );
|
||||
}
|
||||
|
||||
|
@ -4407,6 +4421,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_new_thread_request,
|
||||
(dump_func)dump_get_startup_info_request,
|
||||
(dump_func)dump_init_process_done_request,
|
||||
(dump_func)dump_init_first_thread_request,
|
||||
(dump_func)dump_init_thread_request,
|
||||
(dump_func)dump_terminate_process_request,
|
||||
(dump_func)dump_terminate_thread_request,
|
||||
|
@ -4685,6 +4700,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_new_thread_reply,
|
||||
(dump_func)dump_get_startup_info_reply,
|
||||
(dump_func)dump_init_process_done_reply,
|
||||
(dump_func)dump_init_first_thread_reply,
|
||||
(dump_func)dump_init_thread_reply,
|
||||
(dump_func)dump_terminate_process_reply,
|
||||
(dump_func)dump_terminate_thread_reply,
|
||||
|
@ -4963,6 +4979,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"new_thread",
|
||||
"get_startup_info",
|
||||
"init_process_done",
|
||||
"init_first_thread",
|
||||
"init_thread",
|
||||
"terminate_process",
|
||||
"terminate_thread",
|
||||
|
|
Loading…
Reference in New Issue