Pass the pid of the new process in the new_process request, don't
depend on the parent pid to find the startup info.
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 260361e..c5b5e4c 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -185,6 +185,7 @@
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 request_header __header;
void* ldt_copy;
- int ppid;
};
struct init_process_reply
{
@@ -3551,6 +3551,6 @@
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 136e139..e5a41dd 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -416,7 +416,6 @@
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 @@
/***********************************************************************
* 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 @@
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 @@
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 @@
}
if (pid == -1) FILE_SetDosError();
close( fd[0] );
- if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env );
return pid;
}
@@ -957,6 +946,74 @@
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 @@
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 @@
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 d616d42..be62975 100644
--- a/server/process.c
+++ b/server/process.c
@@ -81,9 +81,11 @@
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 struct list startup_info_list = LIST_INIT(startup_info_list);
+
struct ptid_entry
{
void *ptr; /* entry ptr */
@@ -326,23 +330,36 @@
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 @@
{
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 @@
{
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 @@
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 @@
}
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 bab120e..805ad8b 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -199,6 +199,7 @@
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 @@
/* 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 1c8dbce..2b53d59 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -116,7 +116,6 @@
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 @@
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 314ceab..250174f 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -31,7 +31,6 @@
struct mutex;
struct debug_ctx;
struct debug_event;
-struct startup_info;
struct msg_queue;
struct hook_table;
@@ -69,7 +68,6 @@
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 7611f7e..65d05cf 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -354,6 +354,7 @@
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_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 )