From c316f0e47fd75c8cc2ddf77b847d59b0e8f475d2 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 19 Jul 2006 14:00:10 +0200 Subject: [PATCH] server: Simplify process creation. Pass the socket for the new process from the parent through the environment. Perform initialisations during the new_process request. --- dlls/kernel/process.c | 212 ++++++++++++++----------------- dlls/ntdll/server.c | 23 +++- include/wine/server_protocol.h | 21 ++-- server/process.c | 220 ++++++++++++++------------------- server/process.h | 2 +- server/protocol.def | 37 +++--- server/request.c | 2 +- server/trace.c | 25 ++-- 8 files changed, 250 insertions(+), 292 deletions(-) diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c index 911cf511ca8..ec92bb11dfc 100644 --- a/dlls/kernel/process.c +++ b/dlls/kernel/process.c @@ -31,6 +31,12 @@ #ifdef HAVE_SYS_TIME_H # include #endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif #ifdef HAVE_SYS_PRCTL_H # include #endif @@ -1104,6 +1110,7 @@ static char **build_envp( const WCHAR *envW ) { if (*p == '=') continue; /* skip drive curdirs, this crashes some unix apps */ if (!strncmp( p, "WINEPRELOADRESERVE=", sizeof("WINEPRELOADRESERVE=")-1 )) continue; + if (!strncmp( p, "WINESERVERSOCKET=", sizeof("WINESERVERSOCKET=")-1 )) continue; if (is_special_env_var( p )) /* prefix it with "WINE" */ *envptr++ = alloc_env_string( "WINE", p ); else @@ -1210,9 +1217,18 @@ static RTL_USER_PROCESS_PARAMETERS *create_user_params( LPCWSTR filename, LPCWST if (flags & CREATE_NEW_PROCESS_GROUP) params->ConsoleFlags = 1; if (flags & CREATE_NEW_CONSOLE) params->ConsoleHandle = (HANDLE)1; /* FIXME: cf. kernel_main.c */ - params->hStdInput = startup->hStdInput; - params->hStdOutput = startup->hStdOutput; - params->hStdError = startup->hStdError; + if (startup->dwFlags & STARTF_USESTDHANDLES) + { + params->hStdInput = startup->hStdInput; + params->hStdOutput = startup->hStdOutput; + params->hStdError = startup->hStdError; + } + else + { + params->hStdInput = GetStdHandle( STD_INPUT_HANDLE ); + params->hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE ); + params->hStdError = GetStdHandle( STD_ERROR_HANDLE ); + } params->dwX = startup->dwX; params->dwY = startup->dwY; params->dwXSize = startup->dwXSize; @@ -1243,12 +1259,9 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW WCHAR *env_end; char *winedebug = NULL; RTL_USER_PROCESS_PARAMETERS *params; - int startfd[2]; - int execfd[2]; + int socketfd[2]; pid_t pid; int err; - char dummy = 0; - char preloader_reserve[64]; if (!env) RtlAcquirePebLock(); @@ -1271,96 +1284,34 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW } env_end++; - sprintf( preloader_reserve, "WINEPRELOADRESERVE=%lx-%lx%c", - (unsigned long)res_start, (unsigned long)res_end, 0 ); + /* create the socket for the new process */ - /* create the synchronization pipes */ - - if (pipe( startfd ) == -1) + if (socketpair( PF_UNIX, SOCK_STREAM, 0, socketfd ) == -1) { if (!env) RtlReleasePebLock(); HeapFree( GetProcessHeap(), 0, winedebug ); + RtlDestroyProcessParameters( params ); SetLastError( ERROR_TOO_MANY_OPEN_FILES ); - RtlDestroyProcessParameters( params ); - return FALSE; - } - if (pipe( execfd ) == -1) - { - if (!env) RtlReleasePebLock(); - HeapFree( GetProcessHeap(), 0, winedebug ); - SetLastError( ERROR_TOO_MANY_OPEN_FILES ); - close( startfd[0] ); - close( startfd[1] ); - RtlDestroyProcessParameters( params ); - 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 ); - - 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] ); - if (flags & (CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE | DETACHED_PROCESS)) setsid(); - - /* Reset signals that we previously set to SIG_IGN */ - signal( SIGPIPE, SIG_DFL ); - signal( SIGCHLD, SIG_DFL ); - - putenv( preloader_reserve ); - if (winedebug) putenv( winedebug ); - if (unixdir) chdir(unixdir); - - if (argv) wine_exec_wine_binary( NULL, argv, getenv("WINELOADER") ); - - err = errno; - write( execfd[1], &err, sizeof(err) ); - _exit(1); - } - - /* this is the parent */ - - close( startfd[0] ); - close( execfd[1] ); - HeapFree( GetProcessHeap(), 0, winedebug ); - if (pid == -1) - { - if (!env) RtlReleasePebLock(); - close( startfd[1] ); - close( execfd[0] ); - FILE_SetDosError(); - RtlDestroyProcessParameters( params ); return FALSE; } + wine_server_send_fd( socketfd[1] ); + close( socketfd[1] ); /* create the process on the server side */ SERVER_START_REQ( new_process ) { - req->inherit_all = inherit; - req->create_flags = flags; - req->unix_pid = pid; - req->exe_file = hFile; - if (startup->dwFlags & STARTF_USESTDHANDLES) - { - req->hstdin = startup->hStdInput; - req->hstdout = startup->hStdOutput; - req->hstderr = startup->hStdError; - } - else - { - req->hstdin = GetStdHandle( STD_INPUT_HANDLE ); - req->hstdout = GetStdHandle( STD_OUTPUT_HANDLE ); - req->hstderr = GetStdHandle( STD_ERROR_HANDLE ); - } + req->inherit_all = inherit; + req->create_flags = flags; + req->socket_fd = socketfd[1]; + req->exe_file = hFile; + req->process_access = PROCESS_ALL_ACCESS; + req->process_attr = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle) ? OBJ_INHERIT : 0; + req->thread_access = THREAD_ALL_ACCESS; + req->thread_attr = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle) ? OBJ_INHERIT : 0; + req->hstdin = params->hStdInput; + req->hstdout = params->hStdOutput; + req->hstderr = params->hStdError; if ((flags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)) != 0) { @@ -1378,7 +1329,13 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW wine_server_add_data( req, params, params->Size ); wine_server_add_data( req, params->Environment, (env_end-params->Environment)*sizeof(WCHAR) ); - ret = !wine_server_call_err( req ); + if ((ret = !wine_server_call_err( req ))) + { + info->dwProcessId = (DWORD)reply->pid; + info->dwThreadId = (DWORD)reply->tid; + info->hProcess = reply->phandle; + info->hThread = reply->thandle; + } process_info = reply->info; } SERVER_END_REQ; @@ -1387,57 +1344,74 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW RtlDestroyProcessParameters( params ); if (!ret) { - close( startfd[1] ); - close( execfd[0] ); + close( socketfd[0] ); + HeapFree( GetProcessHeap(), 0, winedebug ); return FALSE; } - /* tell child to start and wait for it to exec */ + /* create the child process */ - write( startfd[1], &dummy, 1 ); - close( startfd[1] ); - - if (read( execfd[0], &err, sizeof(err) ) > 0) /* exec failed */ + if (!(pid = fork())) /* child */ { - errno = err; - FILE_SetDosError(); - close( execfd[0] ); - CloseHandle( process_info ); - return FALSE; + char preloader_reserve[64], socket_env[64]; + char **argv = build_argv( cmd_line, 1 ); + + if (flags & (CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE | DETACHED_PROCESS)) setsid(); + + /* Reset signals that we previously set to SIG_IGN */ + signal( SIGPIPE, SIG_DFL ); + signal( SIGCHLD, SIG_DFL ); + + sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd[0] ); + sprintf( preloader_reserve, "WINEPRELOADRESERVE=%lx-%lx", + (unsigned long)res_start, (unsigned long)res_end ); + + putenv( preloader_reserve ); + putenv( socket_env ); + if (winedebug) putenv( winedebug ); + if (unixdir) chdir(unixdir); + + if (argv) wine_exec_wine_binary( NULL, argv, getenv("WINELOADER") ); + _exit(1); + } + + /* this is the parent */ + + close( socketfd[0] ); + HeapFree( GetProcessHeap(), 0, winedebug ); + if (pid == -1) + { + FILE_SetDosError(); + goto error; } - close( execfd[0] ); /* wait for the new process info to be ready */ WaitForSingleObject( process_info, INFINITE ); SERVER_START_REQ( get_new_process_info ) { - req->info = process_info; - req->process_access = PROCESS_ALL_ACCESS; - req->process_attr = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle) ? OBJ_INHERIT : 0; - req->thread_access = THREAD_ALL_ACCESS; - req->thread_attr = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle) ? OBJ_INHERIT : 0; - if ((ret = !wine_server_call_err( req ))) - { - info->dwProcessId = (DWORD)reply->pid; - info->dwThreadId = (DWORD)reply->tid; - info->hProcess = reply->phandle; - info->hThread = reply->thandle; - success = reply->success; - } + req->info = process_info; + wine_server_call( req ); + success = reply->success; + err = reply->exit_code; } SERVER_END_REQ; - if (ret && !success) /* new process failed to start */ + if (!success) { - DWORD exitcode; - if (GetExitCodeProcess( info->hProcess, &exitcode )) SetLastError( exitcode ); - CloseHandle( info->hThread ); - CloseHandle( info->hProcess ); - ret = FALSE; + SetLastError( err ? err : ERROR_INTERNAL_ERROR ); + goto error; } CloseHandle( process_info ); - return ret; + return success; + +error: + CloseHandle( process_info ); + CloseHandle( info->hProcess ); + CloseHandle( info->hThread ); + info->hProcess = info->hThread = 0; + info->dwProcessId = info->dwThreadId = 0; + return FALSE; } diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index b10a391019b..a64bdb6036f 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -843,16 +843,27 @@ static void create_config_dir(void) void server_init_process(void) { obj_handle_t dummy_handle; - const char *server_dir = wine_get_server_dir(); + const char *env_socket = getenv( "WINESERVERSOCKET" ); - if (!server_dir) /* this means the config dir doesn't exist */ + if (env_socket) { - create_config_dir(); - server_dir = wine_get_server_dir(); + fd_socket = atoi( env_socket ); + if (fcntl( fd_socket, F_SETFD, 1 ) == -1) + fatal_perror( "Bad server socket %d", fd_socket ); } + else + { + const char *server_dir = wine_get_server_dir(); - /* connect to the server */ - fd_socket = server_connect( server_dir ); + if (!server_dir) /* this means the config dir doesn't exist */ + { + create_config_dir(); + server_dir = wine_get_server_dir(); + } + + /* connect to the server */ + fd_socket = server_connect( server_dir ); + } /* setup the signal mask */ sigemptyset( &block_set ); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 3c8f487fa9e..2755827729c 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -193,11 +193,15 @@ struct new_process_request struct request_header __header; int inherit_all; unsigned int create_flags; - int unix_pid; + int socket_fd; obj_handle_t exe_file; obj_handle_t hstdin; obj_handle_t hstdout; obj_handle_t hstderr; + unsigned int process_access; + unsigned int process_attr; + unsigned int thread_access; + unsigned int thread_attr; /* VARARG(info,startup_info); */ /* VARARG(env,unicode_str); */ }; @@ -205,6 +209,10 @@ struct new_process_reply { struct reply_header __header; obj_handle_t info; + process_id_t pid; + obj_handle_t phandle; + thread_id_t tid; + obj_handle_t thandle; }; @@ -213,19 +221,12 @@ struct get_new_process_info_request { struct request_header __header; obj_handle_t info; - unsigned int process_access; - unsigned int process_attr; - unsigned int thread_access; - unsigned int thread_attr; }; struct get_new_process_info_reply { struct reply_header __header; - process_id_t pid; - obj_handle_t phandle; - thread_id_t tid; - obj_handle_t thandle; int success; + int exit_code; }; @@ -4382,6 +4383,6 @@ union generic_reply struct query_symlink_reply query_symlink_reply; }; -#define SERVER_PROTOCOL_VERSION 237 +#define SERVER_PROTOCOL_VERSION 238 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/process.c b/server/process.c index 0c71540bbc5..231eb2f90bd 100644 --- a/server/process.c +++ b/server/process.c @@ -94,17 +94,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 */ - unsigned int create_flags; /* creation flags */ - int 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 */ struct file *exe_file; /* file handle for main exe */ - struct thread *owner; /* owner thread (the one that created the new process) */ struct process *process; /* created process */ - struct thread *thread; /* created thread */ size_t data_size; /* size of startup data */ void *data; /* data for startup info */ }; @@ -130,8 +124,6 @@ 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 */ @@ -226,13 +218,18 @@ static void set_process_startup_state( struct process *process, enum startup_sta } /* create a new process and its main thread */ -struct thread *create_process( int fd ) +/* if the function fails the fd is closed */ +struct thread *create_process( int fd, struct thread *parent_thread, int inherit_all ) { struct process *process; struct thread *thread = NULL; int request_pipe[2]; - if (!(process = alloc_object( &process_ops ))) goto error; + if (!(process = alloc_object( &process_ops ))) + { + close( fd ); + goto error; + } process->parent = NULL; process->debugger = NULL; process->handles = NULL; @@ -261,9 +258,24 @@ struct thread *create_process( int fd ) gettimeofday( &process->start_time, NULL ); list_add_head( &process_list, &process->entry ); - if (!(process->id = process->group_id = alloc_ptid( process ))) goto error; + if (!(process->id = process->group_id = alloc_ptid( process ))) + { + close( fd ); + goto error; + } if (!(process->msg_fd = create_anonymous_fd( &process_fd_ops, fd, &process->obj ))) goto error; + /* create the handle table */ + if (!parent_thread) process->handles = alloc_handle_table( process, 0 ); + else + { + struct process *parent = parent_thread->process; + process->parent = (struct process *)grab_object( parent ); + process->handles = inherit_all ? copy_handle_table( process, parent ) + : alloc_handle_table( process, 0 ); + } + if (!process->handles) goto error; + /* create the main thread */ if (pipe( request_pipe ) == -1) { @@ -290,82 +302,13 @@ 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( int 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 */ size_t init_process( struct thread *thread ) { struct process *process = thread->process; - struct thread *parent_thread = NULL; - struct process *parent = NULL; - struct startup_info *info; - - if (process->startup_info) return process->startup_info->data_size; /* already initialized */ - - if ((info = find_startup_info( thread->unix_pid ))) - { - if (info->thread) return info->data_size; /* already initialized */ - - info->thread = (struct thread *)grab_object( thread ); - info->process = (struct process *)grab_object( process ); - process->startup_info = (struct startup_info *)grab_object( info ); - - parent_thread = info->owner; - parent = parent_thread->process; - process->parent = (struct process *)grab_object( parent ); - - /* set the process flags */ - process->create_flags = info->create_flags; - - if (info->inherit_all) process->handles = copy_handle_table( process, parent ); - } - - /* create the handle table */ - if (!process->handles) process->handles = alloc_handle_table( process, 0 ); - if (!process->handles) - { - set_error( STATUS_NO_MEMORY ); - return 0; - } - - /* connect to the window station */ - connect_process_winstation( process, parent_thread ); + struct startup_info *info = process->startup_info; if (!info) return 0; - - /* thread will be actually suspended in init_done */ - if (info->create_flags & CREATE_SUSPENDED) thread->suspend++; - - /* set the process console */ - if (!(info->create_flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE))) - { - /* FIXME: some better error checking should be done... - * like if hConOut and hConIn are console handles, then they should be on the same - * physical console - */ - inherit_console( parent_thread, process, info->inherit_all ? info->hstdin : 0 ); - } - - /* attach to the debugger if requested */ - if (process->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) - set_process_debugger( process, parent_thread ); - else if (parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS)) - set_process_debugger( process, parent->debugger ); - - if (!(process->create_flags & CREATE_NEW_PROCESS_GROUP)) - process->group_id = parent->group_id; - return info->data_size; } @@ -426,12 +369,9 @@ 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) release_object( info->owner ); } static void startup_info_dump( struct object *obj, int verbose ) @@ -439,8 +379,8 @@ static void startup_info_dump( struct object *obj, int verbose ) struct startup_info *info = (struct startup_info *)obj; assert( obj->ops == &startup_info_ops ); - fprintf( stderr, "Startup info flags=%x in=%p out=%p err=%p\n", - info->create_flags, info->hstdin, info->hstdout, info->hstderr ); + fprintf( stderr, "Startup info in=%p out=%p err=%p\n", + info->hstdin, info->hstdout, info->hstderr ); } static int startup_info_signaled( struct object *obj, struct thread *thread ) @@ -792,20 +732,30 @@ struct module_snapshot *module_snap( struct process *process, int *count ) DECL_HANDLER(new_process) { struct startup_info *info; + struct thread *thread; + struct process *process; + struct process *parent = current->process; + int socket_fd = thread_get_inflight_fd( current, req->socket_fd ); + + if (socket_fd == -1) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + if (fcntl( socket_fd, F_SETFL, O_NONBLOCK ) == -1) + { + set_error( STATUS_INVALID_HANDLE ); + close( socket_fd ); + 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->create_flags = req->create_flags; - info->unix_pid = req->unix_pid; info->hstdin = req->hstdin; info->hstdout = req->hstdout; info->hstderr = req->hstderr; info->exe_file = NULL; - info->owner = (struct thread *)grab_object( current ); info->process = NULL; - info->thread = NULL; info->data_size = get_req_data_size(); info->data = NULL; @@ -814,7 +764,56 @@ DECL_HANDLER(new_process) goto done; if (!(info->data = memdup( get_req_data(), info->data_size ))) goto done; + + if (!(thread = create_process( socket_fd, current, req->inherit_all ))) goto done; + process = thread->process; + process->create_flags = req->create_flags; + process->startup_info = (struct startup_info *)grab_object( info ); + + /* connect to the window station */ + connect_process_winstation( process, current ); + + /* thread will be actually suspended in init_done */ + if (req->create_flags & CREATE_SUSPENDED) thread->suspend++; + + /* set the process console */ + if (!(req->create_flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE))) + { + /* FIXME: some better error checking should be done... + * like if hConOut and hConIn are console handles, then they should be on the same + * physical console + */ + inherit_console( current, process, req->inherit_all ? req->hstdin : 0 ); + } + + if (!req->inherit_all && !(req->create_flags & CREATE_NEW_CONSOLE)) + { + info->hstdin = duplicate_handle( parent, req->hstdin, process, + 0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS ); + info->hstdout = duplicate_handle( parent, req->hstdout, process, + 0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS ); + info->hstderr = duplicate_handle( parent, req->hstderr, process, + 0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS ); + /* some handles above may have been invalid; this is not an error */ + if (get_error() == STATUS_INVALID_HANDLE || + get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error(); + } + + /* attach to the debugger if requested */ + if (req->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) + set_process_debugger( process, current ); + else if (parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS)) + set_process_debugger( process, parent->debugger ); + + if (!(req->create_flags & CREATE_NEW_PROCESS_GROUP)) + process->group_id = parent->group_id; + + info->process = (struct process *)grab_object( process ); reply->info = alloc_handle( current->process, info, SYNCHRONIZE, 0 ); + reply->pid = get_process_id( process ); + reply->tid = get_thread_id( thread ); + reply->phandle = alloc_handle( parent, process, req->process_access, req->process_attr ); + reply->thandle = alloc_handle( parent, thread, req->thread_access, req->thread_attr ); done: release_object( info ); @@ -828,23 +827,10 @@ DECL_HANDLER(get_new_process_info) if ((info = (struct startup_info *)get_handle_obj( current->process, req->info, 0, &startup_info_ops ))) { - reply->pid = get_process_id( info->process ); - reply->tid = get_thread_id( info->thread ); - reply->phandle = alloc_handle( current->process, info->process, - req->process_access, req->process_attr ); - reply->thandle = alloc_handle( current->process, info->thread, - req->thread_access, req->thread_attr ); reply->success = is_process_init_done( info->process ); + reply->exit_code = info->process->exit_code; release_object( info ); } - else - { - reply->pid = 0; - reply->tid = 0; - reply->phandle = 0; - reply->thandle = 0; - reply->success = 0; - } } /* Retrieve the new process startup info */ @@ -859,25 +845,9 @@ DECL_HANDLER(get_startup_info) if (info->exe_file && !(reply->exe_file = alloc_handle( process, info->exe_file, GENERIC_READ, 0 ))) return; - if (!info->inherit_all && !(info->create_flags & CREATE_NEW_CONSOLE)) - { - struct process *parent_process = info->owner->process; - reply->hstdin = duplicate_handle( parent_process, info->hstdin, process, - 0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS ); - reply->hstdout = duplicate_handle( parent_process, info->hstdout, process, - 0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS ); - reply->hstderr = duplicate_handle( parent_process, info->hstderr, process, - 0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS ); - /* some handles above may have been invalid; this is not an error */ - if (get_error() == STATUS_INVALID_HANDLE || - get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error(); - } - else - { - reply->hstdin = info->hstdin; - reply->hstdout = info->hstdout; - reply->hstderr = info->hstderr; - } + reply->hstdin = info->hstdin; + reply->hstdout = info->hstdout; + reply->hstderr = info->hstderr; /* we return the data directly without making a copy so this can only be called once */ size = info->data_size; diff --git a/server/process.h b/server/process.h index baf2632ed95..e5289daef41 100644 --- a/server/process.h +++ b/server/process.h @@ -102,7 +102,7 @@ struct module_snapshot extern unsigned int alloc_ptid( void *ptr ); extern void free_ptid( unsigned int id ); extern void *get_ptid_entry( unsigned int id ); -extern struct thread *create_process( int fd ); +extern struct thread *create_process( int fd, struct thread *parent_thread, int inherit_all ); extern size_t init_process( struct thread *thread ); extern struct thread *get_process_first_thread( struct process *process ); extern struct process *get_process_from_id( process_id_t id ); diff --git a/server/protocol.def b/server/protocol.def index 663f91062e4..eab3115388f 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -205,33 +205,34 @@ struct token_groups /* Create a new process from the context of the parent */ @REQ(new_process) - int inherit_all; /* inherit all handles from parent */ - unsigned 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 */ - obj_handle_t hstderr; /* handle for stderr */ - VARARG(info,startup_info); /* startup information */ - VARARG(env,unicode_str); /* environment for new process */ + int inherit_all; /* inherit all handles from parent */ + unsigned int create_flags; /* creation flags */ + int socket_fd; /* file descriptor for process socket */ + obj_handle_t exe_file; /* file handle for main exe */ + obj_handle_t hstdin; /* handle for stdin */ + obj_handle_t hstdout; /* handle for stdout */ + obj_handle_t hstderr; /* handle for stderr */ + unsigned int process_access; /* access rights for process object */ + unsigned int process_attr; /* attributes for process object */ + unsigned int thread_access; /* access rights for thread object */ + unsigned int thread_attr; /* attributes for thread object */ + VARARG(info,startup_info); /* startup information */ + VARARG(env,unicode_str); /* environment for new process */ @REPLY - obj_handle_t info; /* new process info handle */ + obj_handle_t info; /* new process info handle */ + process_id_t pid; /* process id */ + obj_handle_t phandle; /* process handle (in the current process) */ + thread_id_t tid; /* thread id */ + obj_handle_t thandle; /* thread handle (in the current process) */ @END /* Retrieve information about a newly started process */ @REQ(get_new_process_info) obj_handle_t info; /* info handle returned from new_process_request */ - unsigned int process_access; /* access rights for process object */ - unsigned int process_attr; /* attributes for process object */ - unsigned int thread_access; /* access rights for thread object */ - unsigned int thread_attr; /* attributes for thread object */ @REPLY - process_id_t pid; /* process id */ - obj_handle_t phandle; /* process handle (in the current process) */ - thread_id_t tid; /* thread id */ - obj_handle_t thandle; /* thread handle (in the current process) */ int success; /* did the process start successfully? */ + int exit_code; /* process exit code if failed */ @END diff --git a/server/request.c b/server/request.c index a78916ec4f0..260fc62c362 100644 --- a/server/request.c +++ b/server/request.c @@ -508,7 +508,7 @@ static void master_socket_poll_event( struct fd *fd, int event ) sock->timeout = NULL; } fcntl( client, F_SETFL, O_NONBLOCK ); - create_process( client ); + create_process( client, NULL, 0 ); } } diff --git a/server/trace.c b/server/trace.c index 24e0c6e2f75..b5e40b85659 100644 --- a/server/trace.c +++ b/server/trace.c @@ -606,11 +606,15 @@ static void dump_new_process_request( const struct new_process_request *req ) { fprintf( stderr, " inherit_all=%d,", req->inherit_all ); fprintf( stderr, " create_flags=%08x,", req->create_flags ); - fprintf( stderr, " unix_pid=%d,", req->unix_pid ); + fprintf( stderr, " socket_fd=%d,", req->socket_fd ); fprintf( stderr, " exe_file=%p,", req->exe_file ); fprintf( stderr, " hstdin=%p,", req->hstdin ); fprintf( stderr, " hstdout=%p,", req->hstdout ); fprintf( stderr, " hstderr=%p,", req->hstderr ); + fprintf( stderr, " process_access=%08x,", req->process_access ); + fprintf( stderr, " process_attr=%08x,", req->process_attr ); + fprintf( stderr, " thread_access=%08x,", req->thread_access ); + fprintf( stderr, " thread_attr=%08x,", req->thread_attr ); fprintf( stderr, " info=" ); dump_varargs_startup_info( cur_size ); fputc( ',', stderr ); @@ -620,25 +624,22 @@ static void dump_new_process_request( const struct new_process_request *req ) static void dump_new_process_reply( const struct new_process_reply *req ) { - fprintf( stderr, " info=%p", req->info ); + fprintf( stderr, " info=%p,", req->info ); + fprintf( stderr, " pid=%04x,", req->pid ); + fprintf( stderr, " phandle=%p,", req->phandle ); + fprintf( stderr, " tid=%04x,", req->tid ); + fprintf( stderr, " thandle=%p", req->thandle ); } static void dump_get_new_process_info_request( const struct get_new_process_info_request *req ) { - fprintf( stderr, " info=%p,", req->info ); - fprintf( stderr, " process_access=%08x,", req->process_access ); - fprintf( stderr, " process_attr=%08x,", req->process_attr ); - fprintf( stderr, " thread_access=%08x,", req->thread_access ); - fprintf( stderr, " thread_attr=%08x", req->thread_attr ); + fprintf( stderr, " info=%p", req->info ); } static void dump_get_new_process_info_reply( const struct get_new_process_info_reply *req ) { - fprintf( stderr, " pid=%04x,", req->pid ); - fprintf( stderr, " phandle=%p,", req->phandle ); - fprintf( stderr, " tid=%04x,", req->tid ); - fprintf( stderr, " thandle=%p,", req->thandle ); - fprintf( stderr, " success=%d", req->success ); + fprintf( stderr, " success=%d,", req->success ); + fprintf( stderr, " exit_code=%d", req->exit_code ); } static void dump_new_thread_request( const struct new_thread_request *req )