Pass the pid of the new process in the new_process request, don't
authorAlexandre Julliard <julliard@winehq.org>
Mon, 24 Feb 2003 20:51:50 +0000 (20:51 +0000)
committerAlexandre Julliard <julliard@winehq.org>
Mon, 24 Feb 2003 20:51:50 +0000 (20:51 +0000)
depend on the parent pid to find the startup info.

include/wine/server_protocol.h
scheduler/process.c
server/process.c
server/protocol.def
server/thread.c
server/thread.h
server/trace.c

index 260361e571a649d258d05b5643f97d015aaead67..c5b5e4c7be9df9bb5f45c3eeb1a8dea236c33077 100644 (file)
@@ -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 */
index 136e139cc627ac03506e80c47b3a934fc257ffab..e5a41dd1e7456b88d049ffde18f7d065d43acc5f 100644 (file)
@@ -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 (!ret)
+    {
+        close( startfd[1] );
+        close( execfd[0] );
+        return FALSE;
+    }
+
+    /* tell child to start and wait for it to exec */
 
-    if (fork_and_exec( NULL, cmd_line, env, unixdir ) == -1)
+    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;
     }
index d616d42cab2d9ba9568642000d4046fdb834927e..be629750ae37fdb49b97f6dd2356c724eac7e375 100644 (file)
@@ -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 */
index bab120ea3f5049d71e56700eec8c3616e55d2d05..805ad8b6fdd14e285a0334b90260ffef894d5bf1 100644 (file)
@@ -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) */
index 1c8dbcea65ad1bb9a4ebbd24da18aab7406005ca..2b53d598c83a52864cb214d0547871ec7c94b8c0 100644 (file)
@@ -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 );
index 314ceabdbfa233bff0b302499604dd9f3b74f2e3..250174f303b8c4d06eaa1e82d63c1043e488168a 100644 (file)
@@ -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 */
index 7611f7e9f5bc896c374492e235b8434e3b0f12ad..65d05cf749971ac63d2ce79e480e69bf0068f344 100644 (file)
@@ -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 )