Made the server listen for new clients on a Unix socket in
$HOME/.wine. Newly started wine processes now attach to an existing
server if one is running.
diff --git a/server/process.c b/server/process.c
index b2a53e4..b2743e1 100644
--- a/server/process.c
+++ b/server/process.c
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
+#include <sys/socket.h>
#include <unistd.h>
#include "winbase.h"
@@ -50,14 +51,89 @@
process_destroy /* destroy */
};
+/* set the process creation info */
+static int set_creation_info( struct process *process, struct new_process_request *req,
+ const char *cmd_line, size_t len )
+{
+ if (!(process->info = mem_alloc( sizeof(*process->info) + len ))) return 0;
+ if (req)
+ {
+ /* copy the request structure */
+ memcpy( process->info, req, sizeof(*req) );
+ }
+ else /* no request, use defaults */
+ {
+ req = process->info;
+ req->inherit = 0;
+ req->inherit_all = 0;
+ req->create_flags = CREATE_NEW_CONSOLE;
+ req->start_flags = STARTF_USESTDHANDLES;
+ req->hstdin = -1;
+ req->hstdout = -1;
+ req->hstderr = -1;
+ req->event = -1;
+ req->cmd_show = 0;
+ req->env_ptr = NULL;
+ }
+ memcpy( process->info->cmdline, cmd_line, len );
+ process->info->cmdline[len] = 0;
+ process->create_flags = process->info->create_flags;
+ return 1;
+}
-/* create a new process */
-static struct process *create_process( struct process *parent, struct new_process_request *req,
- const char *cmd_line, size_t len )
+/* set the console and stdio handles for a newly created process */
+static int set_process_console( struct process *process, struct process *parent )
+{
+ struct new_process_request *info = process->info;
+
+ if (process->create_flags & CREATE_NEW_CONSOLE)
+ {
+ if (!alloc_console( process )) return 0;
+ }
+ else if (!(process->create_flags & DETACHED_PROCESS))
+ {
+ if (parent->console_in) process->console_in = grab_object( parent->console_in );
+ if (parent->console_out) process->console_out = grab_object( parent->console_out );
+ }
+ if (parent)
+ {
+ if (!info->inherit_all && !(info->start_flags & STARTF_USESTDHANDLES))
+ {
+ /* duplicate the handle from the parent into this process */
+ info->hstdin = duplicate_handle( parent, info->hstdin, process,
+ 0, TRUE, DUPLICATE_SAME_ACCESS );
+ info->hstdout = duplicate_handle( parent, info->hstdout, process,
+ 0, TRUE, DUPLICATE_SAME_ACCESS );
+ info->hstderr = duplicate_handle( parent, info->hstderr, process,
+ 0, TRUE, DUPLICATE_SAME_ACCESS );
+ }
+ }
+ else
+ {
+ /* no parent, use handles to the console for stdio */
+ info->hstdin = alloc_handle( process, process->console_in,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
+ info->hstdout = alloc_handle( process, process->console_out,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
+ info->hstderr = alloc_handle( process, process->console_out,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
+ }
+ return 1;
+}
+
+/* create a new process and its main thread */
+struct thread *create_process( int fd, struct process *parent,
+ struct new_process_request *req,
+ const char *cmd_line, size_t len )
{
struct process *process;
+ struct thread *thread = NULL;
- if (!(process = alloc_object( &process_ops, -1 ))) return NULL;
+ if (!(process = alloc_object( &process_ops, -1 )))
+ {
+ close( fd );
+ return NULL;
+ }
process->next = NULL;
process->prev = NULL;
process->thread_list = NULL;
@@ -74,16 +150,13 @@
process->init_event = NULL;
process->info = NULL;
gettimeofday( &process->start_time, NULL );
+ if ((process->next = first_process) != NULL) process->next->prev = process;
+ first_process = process;
/* copy the request structure */
- if (!(process->info = mem_alloc( sizeof(*process->info) + len ))) goto error;
- memcpy( process->info, req, sizeof(*req) );
- memcpy( process->info->cmdline, cmd_line, len );
- process->info->cmdline[len] = 0;
- req = process->info; /* use the copy now */
- process->create_flags = req->create_flags;
+ if (!set_creation_info( process, req, cmd_line, len )) goto error;
- if (req->inherit_all)
+ if (process->info->inherit_all)
process->handles = copy_handle_table( process, parent );
else
process->handles = alloc_handle_table( process, 0 );
@@ -93,32 +166,18 @@
alloc_handle( process, process, PROCESS_ALL_ACCESS, 0 );
/* get the init done event */
- if (req->event != -1)
+ if (process->info->event != -1)
{
- if (!(process->init_event = get_event_obj( parent, req->event, EVENT_MODIFY_STATE )))
- goto error;
+ if (!(process->init_event = get_event_obj( parent, process->info->event,
+ EVENT_MODIFY_STATE ))) goto error;
}
/* set the process console */
- if (process->create_flags & CREATE_NEW_CONSOLE)
- {
- if (!alloc_console( process )) goto error;
- }
- else if (!(process->create_flags & DETACHED_PROCESS))
- {
- if (parent->console_in) process->console_in = grab_object( parent->console_in );
- if (parent->console_out) process->console_out = grab_object( parent->console_out );
- }
+ if (!set_process_console( process, parent )) goto error;
- if (!req->inherit_all && !(req->start_flags & STARTF_USESTDHANDLES))
- {
- process->info->hstdin = duplicate_handle( parent, req->hstdin, process,
- 0, TRUE, DUPLICATE_SAME_ACCESS );
- process->info->hstdout = duplicate_handle( parent, req->hstdout, process,
- 0, TRUE, DUPLICATE_SAME_ACCESS );
- process->info->hstderr = duplicate_handle( parent, req->hstderr, process,
- 0, TRUE, DUPLICATE_SAME_ACCESS );
- }
+ /* create the main thread */
+ if (!(thread = create_thread( fd, process, (process->create_flags & CREATE_SUSPENDED) != 0)))
+ goto error;
/* attach to the debugger if requested */
if (process->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
@@ -126,45 +185,17 @@
else if (parent && parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
debugger_attach( process, parent->debugger );
- if ((process->next = first_process) != NULL) process->next->prev = process;
- first_process = process;
- return process;
+ release_object( process );
+ return thread;
error:
+ close( fd );
free_console( process );
if (process->handles) release_object( process->handles );
release_object( process );
return NULL;
}
-/* create the initial process */
-struct process *create_initial_process(void)
-{
- struct process *process;
- struct new_process_request req;
-
- req.inherit = 0;
- req.inherit_all = 0;
- req.create_flags = CREATE_NEW_CONSOLE;
- req.start_flags = STARTF_USESTDHANDLES;
- req.hstdin = -1;
- req.hstdout = -1;
- req.hstderr = -1;
- req.event = -1;
- req.cmd_show = 0;
- req.env_ptr = NULL;
- if ((process = create_process( NULL, &req, "", 1 )))
- {
- process->info->hstdin = alloc_handle( process, process->console_in,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
- process->info->hstdout = alloc_handle( process, process->console_out,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
- process->info->hstderr = alloc_handle( process, process->console_out,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
- }
- return process;
-}
-
/* destroy a process when its refcount is 0 */
static void process_destroy( struct object *obj )
{
@@ -229,6 +260,8 @@
{
/* last process died, close global handles */
close_global_handles();
+ /* this will cause the select loop to terminate */
+ if (!persistent_server) close_master_socket();
}
}
@@ -455,16 +488,40 @@
DECL_HANDLER(new_process)
{
size_t len = get_req_strlen( req->cmdline );
- struct process *process;
+ struct thread *thread;
+ int sock[2];
- req->handle = -1;
- req->pid = NULL;
- if ((process = create_process( current->process, req, req->cmdline, len )))
+ req->phandle = -1;
+ req->thandle = -1;
+ req->pid = NULL;
+ req->tid = NULL;
+
+ if (socketpair( AF_UNIX, SOCK_STREAM, 0, sock ) == -1)
{
- req->handle = alloc_handle( current->process, process, PROCESS_ALL_ACCESS, req->inherit );
- req->pid = process;
- release_object( process );
+ file_set_error();
+ return;
}
+
+ if ((thread = create_process( sock[0], current->process, req, req->cmdline, len )))
+ {
+ int phandle = alloc_handle( current->process, thread->process,
+ PROCESS_ALL_ACCESS, req->inherit );
+ if ((req->phandle = phandle) != -1)
+ {
+ if ((req->thandle = alloc_handle( current->process, thread,
+ THREAD_ALL_ACCESS, req->inherit )) != -1)
+ {
+ /* thread object will be released when the thread gets killed */
+ set_reply_fd( current, sock[1] );
+ req->pid = thread->process;
+ req->tid = thread;
+ return;
+ }
+ close_handle( current->process, phandle );
+ }
+ release_object( thread );
+ }
+ close( sock[1] );
}
/* initialize a new process */