A few optimizations in the process startup requests now that Winelib
apps are started differently from Unix ones.
diff --git a/server/process.c b/server/process.c
index 55cd67e..9368a81 100644
--- a/server/process.c
+++ b/server/process.c
@@ -74,9 +74,12 @@
/* process startup info */
+enum startup_state { STARTUP_IN_PROGRESS, STARTUP_DONE, STARTUP_ABORTED };
+
struct startup_info
{
struct object obj; /* object header */
+ enum startup_state state; /* child process startup state */
int inherit_all; /* inherit all handles from parent */
int use_handles; /* use stdio handles */
int create_flags; /* creation flags */
@@ -113,6 +116,16 @@
};
+/* set the state of the process startup info */
+static void set_process_startup_state( struct process *process, enum startup_state state )
+{
+ if (!process->startup_info) return;
+ process->startup_info->state = state;
+ wake_up( &process->startup_info->obj, 0 );
+ release_object( process->startup_info );
+ process->startup_info = NULL;
+}
+
/* set the console and stdio handles for a newly created process */
static int set_process_console( struct process *process, struct thread *parent_thread,
struct startup_info *info, struct init_process_reply *reply )
@@ -122,7 +135,7 @@
/* let the process init do the allocation */
return 1;
}
- else if (parent_thread && !(process->create_flags & DETACHED_PROCESS))
+ else if (info && !(process->create_flags & DETACHED_PROCESS))
{
/* FIXME: some better error checking should be done...
* like if hConOut and hConIn are console handles, then they should be on the same
@@ -131,7 +144,7 @@
inherit_console( parent_thread, process,
(info->inherit_all || info->use_handles) ? info->hstdin : 0 );
}
- if (parent_thread)
+ if (info)
{
if (!info->inherit_all && !info->use_handles)
{
@@ -193,7 +206,7 @@
process->suspend = 0;
process->create_flags = 0;
process->console = NULL;
- process->init_event = NULL;
+ process->startup_info = NULL;
process->idle_event = NULL;
process->queue = NULL;
process->atom_table = NULL;
@@ -201,6 +214,7 @@
process->exe.next = NULL;
process->exe.prev = NULL;
process->exe.file = NULL;
+ process->exe.base = NULL;
process->exe.dbg_offset = 0;
process->exe.dbg_size = 0;
process->exe.namelen = 0;
@@ -210,9 +224,6 @@
if ((process->next = first_process) != NULL) process->next->prev = process;
first_process = process;
- /* create the init done event */
- if (!(process->init_event = create_event( NULL, 0, 1, 0 ))) goto error;
-
/* create the main thread */
if (pipe( request_pipe ) == -1)
{
@@ -245,12 +256,7 @@
{
parent = parent_thread->process;
info = parent_thread->info;
- if (!info)
- {
- fatal_protocol_error( current, "init_process: parent but no info\n" );
- return NULL;
- }
- if (info->thread)
+ if (info && info->thread)
{
fatal_protocol_error( current, "init_process: called twice?\n" );
return NULL;
@@ -262,7 +268,7 @@
process->create_flags = info ? info->create_flags : 0;
/* create the handle table */
- if (parent && info->inherit_all)
+ if (info && info->inherit_all)
process->handles = copy_handle_table( process, parent );
else
process->handles = alloc_handle_table( process, 0 );
@@ -270,7 +276,7 @@
/* retrieve the main exe file */
reply->exe_file = 0;
- if (parent && info->exe_file)
+ if (info && info->exe_file)
{
process->exe.file = (struct file *)grab_object( info->exe_file );
if (!(reply->exe_file = alloc_handle( process, process->exe.file, GENERIC_READ, 0 )))
@@ -285,7 +291,7 @@
/* 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 && parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
+ else if (parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
set_process_debugger( process, parent->debugger );
}
@@ -297,7 +303,6 @@
reply->info_size = info->data_size;
info->process = (struct process *)grab_object( process );
info->thread = (struct thread *)grab_object( current );
- wake_up( &info->obj, 0 );
}
reply->create_flags = process->create_flags;
reply->server_start = server_start_ticks;
@@ -312,12 +317,13 @@
/* we can't have a thread remaining */
assert( !process->thread_list );
+
+ set_process_startup_state( process, STARTUP_ABORTED );
if (process->console) release_object( process->console );
if (process->parent) release_object( process->parent );
if (process->next) process->next->prev = process->prev;
if (process->prev) process->prev->next = process->next;
else first_process = process->next;
- if (process->init_event) release_object( process->init_event );
if (process->idle_event) release_object( process->idle_event );
if (process->queue) release_object( process->queue );
if (process->atom_table) release_object( process->atom_table );
@@ -371,17 +377,16 @@
struct startup_info *info = (struct startup_info *)obj;
assert( obj->ops == &startup_info_ops );
- fprintf( stderr, "Startup info flags=%x in=%d out=%d err=%d\n",
- info->create_flags, info->hstdin, info->hstdout, info->hstderr );
+ fprintf( stderr, "Startup info flags=%x in=%d out=%d err=%d state=%d\n",
+ info->create_flags, info->hstdin, info->hstdout, info->hstderr, info->state );
}
static int startup_info_signaled( struct object *obj, struct thread *thread )
{
struct startup_info *info = (struct startup_info *)obj;
- return (info->thread != NULL);
+ return info->state != STARTUP_IN_PROGRESS;
}
-
/* get a process from an id (and increment the refcount) */
struct process *get_process_from_id( void *id )
{
@@ -490,6 +495,7 @@
if (dll->filename) free( dll->filename );
free( dll );
}
+ set_process_startup_state( process, STARTUP_ABORTED );
if (process->exe.file) release_object( process->exe.file );
process->exe.file = NULL;
wake_up( &process->obj, 0 );
@@ -776,6 +782,7 @@
/* build the startup info for a new process */
if (!(info = alloc_object( &startup_info_ops, -1 ))) return;
+ info->state = STARTUP_IN_PROGRESS;
info->inherit_all = req->inherit_all;
info->use_handles = req->use_handles;
info->create_flags = req->create_flags;
@@ -807,8 +814,6 @@
{
struct startup_info *info;
- reply->event = 0;
-
if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
0, &startup_info_ops )))
{
@@ -818,9 +823,7 @@
PROCESS_ALL_ACCESS, req->pinherit );
reply->thandle = alloc_handle( current->process, info->thread,
THREAD_ALL_ACCESS, req->tinherit );
- if (info->process->init_event)
- reply->event = alloc_handle( current->process, info->process->init_event,
- EVENT_ALL_ACCESS, 0 );
+ reply->success = (info->state == STARTUP_DONE);
release_object( info );
}
else
@@ -829,6 +832,7 @@
reply->tid = 0;
reply->phandle = 0;
reply->thandle = 0;
+ reply->success = 0;
}
}
@@ -837,19 +841,15 @@
{
struct startup_info *info;
- if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
- 0, &startup_info_ops )))
+ if ((info = current->process->startup_info))
{
size_t size = info->data_size;
if (size > get_reply_max_size()) size = get_reply_max_size();
- if (req->close)
- {
- set_reply_data_ptr( info->data, size );
- info->data = NULL;
- close_handle( current->process, req->info, NULL );
- }
- else set_reply_data( info->data, size );
- release_object( info );
+
+ /* we return the data directly without making a copy so this can only be called once */
+ set_reply_data_ptr( info->data, size );
+ info->data = NULL;
+ info->data_size = 0;
}
}
@@ -857,21 +857,19 @@
/* initialize a new process */
DECL_HANDLER(init_process)
{
- struct startup_info *info;
-
- reply->info = 0;
- reply->info_size = 0;
if (!current->unix_pid)
{
fatal_protocol_error( current, "init_process: init_thread not called yet\n" );
return;
}
- current->process->ldt_copy = req->ldt_copy;
- if ((info = init_process( req->ppid, reply )))
+ if (current->process->startup_info)
{
- reply->info = alloc_handle( current->process, info, 0, FALSE );
- release_object( info );
+ fatal_protocol_error( current, "init_process: called twice\n" );
+ return;
}
+ reply->info_size = 0;
+ current->process->ldt_copy = req->ldt_copy;
+ current->process->startup_info = init_process( req->ppid, reply );
}
/* signal the end of the process initialization */
@@ -880,9 +878,14 @@
struct file *file = NULL;
struct process *process = current->process;
- if (!process->init_event)
+ if (is_process_init_done(process))
{
- fatal_protocol_error( current, "init_process_done: no event\n" );
+ fatal_protocol_error( current, "init_process_done: called twice\n" );
+ return;
+ }
+ if (!req->module)
+ {
+ fatal_protocol_error( current, "init_process_done: module base address cannot be 0\n" );
return;
}
process->exe.base = req->module;
@@ -896,10 +899,9 @@
if ((process->exe.namelen = get_req_data_size()))
process->exe.filename = memdup( get_req_data(), process->exe.namelen );
- generate_startup_debug_events( current->process, req->entry );
- set_event( process->init_event );
- release_object( process->init_event );
- process->init_event = NULL;
+ generate_startup_debug_events( process, req->entry );
+ set_process_startup_state( process, STARTUP_DONE );
+
if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 );
if (current->suspend + current->process->suspend > 0) stop_thread( current );
reply->debugged = (current->process->debugger != 0);
@@ -1018,7 +1020,7 @@
dll->dbg_size = req->dbg_size;
dll->name = req->name;
/* only generate event if initialization is done */
- if (!current->process->init_event)
+ if (is_process_init_done( current->process ))
generate_debug_event( current, LOAD_DLL_DEBUG_EVENT, dll );
}
if (file) release_object( file );