From 77c8b1dc2bf44b84a0a7205e74c0c83ccb2717b2 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 24 Feb 2003 20:51:50 +0000 Subject: [PATCH] Pass the pid of the new process in the new_process request, don't depend on the parent pid to find the startup info. --- include/wine/server_protocol.h | 4 +- scheduler/process.c | 110 +++++++++++++++++++++++++++------ server/process.c | 49 +++++++++------ server/protocol.def | 2 +- server/thread.c | 2 - server/thread.h | 2 - server/trace.c | 4 +- 7 files changed, 124 insertions(+), 49 deletions(-) diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 260361e571a..c5b5e4c7be9 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -185,6 +185,7 @@ struct new_process_request int inherit_all; int use_handles; int create_flags; + int unix_pid; obj_handle_t exe_file; obj_handle_t hstdin; obj_handle_t hstdout; @@ -250,7 +251,6 @@ struct init_process_request { struct request_header __header; void* ldt_copy; - int ppid; }; struct init_process_reply { @@ -3551,6 +3551,6 @@ union generic_reply struct get_next_hook_reply get_next_hook_reply; }; -#define SERVER_PROTOCOL_VERSION 97 +#define SERVER_PROTOCOL_VERSION 98 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/scheduler/process.c b/scheduler/process.c index 136e139cc62..e5a41dd1e74 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -416,7 +416,6 @@ static BOOL process_init( char *argv[] ) SERVER_START_REQ( init_process ) { req->ldt_copy = &wine_ldt_copy; - req->ppid = getppid(); if ((ret = !wine_server_call_err( req ))) { main_exe_file = reply->exe_file; @@ -888,20 +887,15 @@ static void exec_wine_binary( char **argv, char **envp ) /*********************************************************************** * fork_and_exec * - * Fork and exec a new Unix process, checking for errors. + * Fork and exec a new Unix binary, checking for errors. */ static int fork_and_exec( const char *filename, char *cmdline, const char *env, const char *newdir ) { int fd[2]; int pid, err; - char *extra_env = NULL; - if (!env) - { - env = GetEnvironmentStringsA(); - extra_env = DRIVE_BuildEnv(); - } + if (!env) env = GetEnvironmentStringsA(); if (pipe(fd) == -1) { @@ -911,8 +905,8 @@ static int fork_and_exec( const char *filename, char *cmdline, fcntl( fd[1], F_SETFD, 1 ); /* set close on exec */ if (!(pid = fork())) /* child */ { - char **argv = build_argv( cmdline, filename ? 0 : 1 ); - char **envp = build_envp( env, extra_env ); + char **argv = build_argv( cmdline, 0 ); + char **envp = build_envp( env, NULL ); close( fd[0] ); /* Reset signals that we previously set to SIG_IGN */ @@ -921,11 +915,7 @@ static int fork_and_exec( const char *filename, char *cmdline, if (newdir) chdir(newdir); - if (argv && envp) - { - if (!filename) exec_wine_binary( argv, envp ); - else execve( filename, argv, envp ); - } + if (argv && envp) execve( filename, argv, envp ); err = errno; write( fd[1], &err, sizeof(err) ); _exit(1); @@ -938,7 +928,6 @@ static int fork_and_exec( const char *filename, char *cmdline, } if (pid == -1) FILE_SetDosError(); close( fd[0] ); - if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env ); return pid; } @@ -957,6 +946,74 @@ static BOOL create_process( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCST BOOL ret, success = FALSE; HANDLE process_info; startup_info_t startup_info; + char *extra_env = NULL; + int startfd[2]; + int execfd[2]; + pid_t pid; + int err; + char dummy; + + if (!env) + { + env = GetEnvironmentStringsA(); + extra_env = DRIVE_BuildEnv(); + } + + /* create the synchronization pipes */ + + if (pipe( startfd ) == -1) + { + FILE_SetDosError(); + return FALSE; + } + if (pipe( execfd ) == -1) + { + close( startfd[0] ); + close( startfd[1] ); + FILE_SetDosError(); + return FALSE; + } + fcntl( execfd[1], F_SETFD, 1 ); /* set close on exec */ + + /* create the child process */ + + if (!(pid = fork())) /* child */ + { + char **argv = build_argv( cmd_line, 1 ); + char **envp = build_envp( env, extra_env ); + + close( startfd[1] ); + close( execfd[0] ); + + /* wait for parent to tell us to start */ + if (read( startfd[0], &dummy, 1 ) != 1) _exit(1); + + close( startfd[0] ); + /* Reset signals that we previously set to SIG_IGN */ + signal( SIGPIPE, SIG_DFL ); + signal( SIGCHLD, SIG_DFL ); + + if (unixdir) chdir(unixdir); + + if (argv && envp) exec_wine_binary( argv, envp ); + + err = errno; + write( execfd[1], &err, sizeof(err) ); + _exit(1); + } + + /* this is the parent */ + + close( startfd[0] ); + close( execfd[1] ); + if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env ); + if (pid == -1) + { + close( startfd[1] ); + close( execfd[0] ); + FILE_SetDosError(); + return FALSE; + } /* fill the startup info structure */ @@ -985,6 +1042,7 @@ static BOOL create_process( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCST req->inherit_all = inherit; req->create_flags = flags; req->use_handles = (startup->dwFlags & STARTF_USESTDHANDLES) != 0; + req->unix_pid = pid; req->exe_file = hFile; if (startup->dwFlags & STARTF_USESTDHANDLES) { @@ -1015,12 +1073,24 @@ static BOOL create_process( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCST process_info = reply->info; } SERVER_END_REQ; - if (!ret) return FALSE; - /* fork and execute */ - - if (fork_and_exec( NULL, cmd_line, env, unixdir ) == -1) + if (!ret) { + close( startfd[1] ); + close( execfd[0] ); + return FALSE; + } + + /* tell child to start and wait for it to exec */ + + write( startfd[1], &dummy, 1 ); + close( startfd[1] ); + + if (read( execfd[0], &err, sizeof(err) ) > 0) /* exec failed */ + { + errno = err; + FILE_SetDosError(); + close( execfd[0] ); CloseHandle( process_info ); return FALSE; } diff --git a/server/process.c b/server/process.c index d616d42cab2..be629750ae3 100644 --- a/server/process.c +++ b/server/process.c @@ -81,9 +81,11 @@ static const struct fd_ops process_fd_ops = struct startup_info { struct object obj; /* object header */ + struct list entry; /* entry in list of startup infos */ int inherit_all; /* inherit all handles from parent */ int use_handles; /* use stdio handles */ int create_flags; /* creation flags */ + pid_t unix_pid; /* Unix pid of new process */ obj_handle_t hstdin; /* handle for stdin */ obj_handle_t hstdout; /* handle for stdout */ obj_handle_t hstderr; /* handle for stderr */ @@ -112,6 +114,8 @@ static const struct object_ops startup_info_ops = }; +static struct list startup_info_list = LIST_INIT(startup_info_list); + struct ptid_entry { void *ptr; /* entry ptr */ @@ -326,23 +330,36 @@ struct thread *create_process( int fd ) return NULL; } +/* find the startup info for a given Unix process */ +inline static struct startup_info *find_startup_info( pid_t unix_pid ) +{ + struct list *ptr; + + LIST_FOR_EACH( ptr, &startup_info_list ) + { + struct startup_info *info = LIST_ENTRY( ptr, struct startup_info, entry ); + if (info->unix_pid == unix_pid) return info; + } + return NULL; +} + /* initialize the current process and fill in the request */ -static struct startup_info *init_process( int ppid, struct init_process_reply *reply ) +static struct startup_info *init_process( struct init_process_reply *reply ) { struct process *process = current->process; - struct thread *parent_thread = get_thread_from_pid( ppid ); + struct thread *parent_thread = NULL; struct process *parent = NULL; - struct startup_info *info = NULL; + struct startup_info *info = find_startup_info( current->unix_pid ); - if (parent_thread) + if (info) { - parent = parent_thread->process; - info = parent_thread->info; - if (info && info->thread) + if (info->thread) { fatal_protocol_error( current, "init_process: called twice?\n" ); return NULL; } + parent_thread = info->owner; + parent = parent_thread->process; process->parent = (struct process *)grab_object( parent ); } @@ -447,15 +464,12 @@ static void startup_info_destroy( struct object *obj ) { struct startup_info *info = (struct startup_info *)obj; assert( obj->ops == &startup_info_ops ); + list_remove( &info->entry ); if (info->data) free( info->data ); if (info->exe_file) release_object( info->exe_file ); if (info->process) release_object( info->process ); if (info->thread) release_object( info->thread ); - if (info->owner) - { - info->owner->info = NULL; - release_object( info->owner ); - } + if (info->owner) release_object( info->owner ); } static void startup_info_dump( struct object *obj, int verbose ) @@ -878,17 +892,13 @@ DECL_HANDLER(new_process) { struct startup_info *info; - if (current->info) - { - fatal_protocol_error( current, "new_process: another process is being created\n" ); - return; - } - /* build the startup info for a new process */ if (!(info = alloc_object( &startup_info_ops ))) return; + list_add_head( &startup_info_list, &info->entry ); info->inherit_all = req->inherit_all; info->use_handles = req->use_handles; info->create_flags = req->create_flags; + info->unix_pid = req->unix_pid; info->hstdin = req->hstdin; info->hstdout = req->hstdout; info->hstderr = req->hstderr; @@ -905,7 +915,6 @@ DECL_HANDLER(new_process) if (!(info->data = mem_alloc( info->data_size ))) goto done; memcpy( info->data, get_req_data(), info->data_size ); - current->info = info; reply->info = alloc_handle( current->process, info, SYNCHRONIZE, FALSE ); done: @@ -972,7 +981,7 @@ DECL_HANDLER(init_process) } reply->info_size = 0; current->process->ldt_copy = req->ldt_copy; - current->process->startup_info = init_process( req->ppid, reply ); + current->process->startup_info = init_process( reply ); } /* signal the end of the process initialization */ diff --git a/server/protocol.def b/server/protocol.def index bab120ea3f5..805ad8b6fdd 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -199,6 +199,7 @@ typedef struct int inherit_all; /* inherit all handles from parent */ int use_handles; /* use stdio handles */ int create_flags; /* creation flags */ + int unix_pid; /* Unix pid of new process */ obj_handle_t exe_file; /* file handle for main exe */ obj_handle_t hstdin; /* handle for stdin */ obj_handle_t hstdout; /* handle for stdout */ @@ -243,7 +244,6 @@ typedef struct /* Initialize a process; called from the new process context */ @REQ(init_process) void* ldt_copy; /* addr of LDT copy */ - int ppid; /* parent Unix pid */ @REPLY int create_flags; /* creation flags */ unsigned int server_start; /* server start time (GetTickCount) */ diff --git a/server/thread.c b/server/thread.c index 1c8dbcea65a..2b53d598c83 100644 --- a/server/thread.c +++ b/server/thread.c @@ -116,7 +116,6 @@ inline static void init_thread_structure( struct thread *thread ) thread->debug_event = NULL; thread->queue = NULL; thread->hooks = NULL; - thread->info = NULL; thread->wait = NULL; thread->system_apc.head = NULL; thread->system_apc.tail = NULL; @@ -243,7 +242,6 @@ static void destroy_thread( struct object *obj ) if (thread->prev) thread->prev->next = thread->next; else first_thread = thread->next; while ((apc = thread_dequeue_apc( thread, 0 ))) free( apc ); - if (thread->info) release_object( thread->info ); cleanup_thread( thread ); release_object( thread->process ); if (thread->id) free_ptid( thread->id ); diff --git a/server/thread.h b/server/thread.h index 314ceabdbfa..250174f303b 100644 --- a/server/thread.h +++ b/server/thread.h @@ -31,7 +31,6 @@ struct thread_apc; struct mutex; struct debug_ctx; struct debug_event; -struct startup_info; struct msg_queue; struct hook_table; @@ -69,7 +68,6 @@ struct thread struct debug_event *debug_event; /* debug event being sent to debugger */ struct msg_queue *queue; /* message queue */ struct hook_table *hooks; /* hooks table */ - struct startup_info *info; /* startup info for child process */ struct thread_wait *wait; /* current wait condition if sleeping */ struct apc_queue system_apc; /* queue of system async procedure calls */ struct apc_queue user_apc; /* queue of user async procedure calls */ diff --git a/server/trace.c b/server/trace.c index 7611f7e9f5b..65d05cf7499 100644 --- a/server/trace.c +++ b/server/trace.c @@ -354,6 +354,7 @@ static void dump_new_process_request( const struct new_process_request *req ) fprintf( stderr, " inherit_all=%d,", req->inherit_all ); fprintf( stderr, " use_handles=%d,", req->use_handles ); fprintf( stderr, " create_flags=%d,", req->create_flags ); + fprintf( stderr, " unix_pid=%d,", req->unix_pid ); fprintf( stderr, " exe_file=%p,", req->exe_file ); fprintf( stderr, " hstdin=%p,", req->hstdin ); fprintf( stderr, " hstdout=%p,", req->hstdout ); @@ -403,8 +404,7 @@ static void dump_boot_done_request( const struct boot_done_request *req ) static void dump_init_process_request( const struct init_process_request *req ) { - fprintf( stderr, " ldt_copy=%p,", req->ldt_copy ); - fprintf( stderr, " ppid=%d", req->ppid ); + fprintf( stderr, " ldt_copy=%p", req->ldt_copy ); } static void dump_init_process_reply( const struct init_process_reply *req )