Added new_process and init_process request.
Split out process creation from thread creation. Changed server initialisation to ensure that we always have a current thread.
This commit is contained in:
parent
4f278bdac1
commit
f692d44607
|
@ -40,20 +40,34 @@ struct cmsg_fd
|
|||
/* which case it isn't necessary to define a structure. */
|
||||
|
||||
|
||||
/* Create a new process from the context of the parent */
|
||||
struct new_process_request
|
||||
{
|
||||
int inherit; /* inherit flag */
|
||||
int inherit_all; /* inherit all handles from parent */
|
||||
int start_flags; /* flags from startup info */
|
||||
int hstdin; /* handle for stdin */
|
||||
int hstdout; /* handle for stdout */
|
||||
int hstderr; /* handle for stderr */
|
||||
};
|
||||
struct new_process_reply
|
||||
{
|
||||
void* pid; /* process id */
|
||||
int handle; /* process handle (in the current process) */
|
||||
};
|
||||
|
||||
|
||||
/* Create a new thread from the context of the parent */
|
||||
struct new_thread_request
|
||||
{
|
||||
void* pid; /* process id for the new thread (or 0 if none yet) */
|
||||
void* pid; /* process id for the new thread */
|
||||
int suspend; /* new thread should be suspended on creation */
|
||||
int tinherit; /* inherit flag for thread handle */
|
||||
int pinherit; /* inherit flag for process handle */
|
||||
int inherit; /* inherit flag */
|
||||
};
|
||||
struct new_thread_reply
|
||||
{
|
||||
void* tid; /* thread id */
|
||||
int thandle; /* thread handle (in the current process) */
|
||||
void* pid; /* process id (created if necessary) */
|
||||
int phandle; /* process handle (in the current process) */
|
||||
int handle; /* thread handle (in the current process) */
|
||||
};
|
||||
|
||||
|
||||
|
@ -64,11 +78,24 @@ struct set_debug_request
|
|||
};
|
||||
|
||||
|
||||
/* Initialize a process; called from the new process context */
|
||||
struct init_process_request
|
||||
{
|
||||
int dummy;
|
||||
};
|
||||
struct init_process_reply
|
||||
{
|
||||
int start_flags; /* flags from startup info */
|
||||
int hstdin; /* handle for stdin */
|
||||
int hstdout; /* handle for stdout */
|
||||
int hstderr; /* handle for stderr */
|
||||
};
|
||||
|
||||
|
||||
/* Initialize a thread; called from the child after fork()/clone() */
|
||||
struct init_thread_request
|
||||
{
|
||||
int unix_pid; /* Unix pid of new thread */
|
||||
char cmd_line[0]; /* Thread command line */
|
||||
};
|
||||
|
||||
|
||||
|
@ -122,7 +149,7 @@ struct get_thread_info_request
|
|||
};
|
||||
struct get_thread_info_reply
|
||||
{
|
||||
void* pid; /* server thread id */
|
||||
void* tid; /* server thread id */
|
||||
int exit_code; /* thread exit code */
|
||||
int priority; /* thread priority level */
|
||||
};
|
||||
|
@ -657,11 +684,9 @@ extern void CLIENT_SendRequest( enum request req, int pass_fd,
|
|||
extern unsigned int CLIENT_WaitReply( int *len, int *passed_fd,
|
||||
int n, ... /* arg_1, len_1, etc. */ );
|
||||
extern unsigned int CLIENT_WaitSimpleReply( void *reply, int len, int *passed_fd );
|
||||
extern int CLIENT_InitServer(void);
|
||||
|
||||
struct _THDB;
|
||||
extern int CLIENT_NewThread( struct _THDB *thdb,
|
||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||
int *thandle, int *phandle );
|
||||
extern int CLIENT_SetDebug( int level );
|
||||
extern int CLIENT_InitThread(void);
|
||||
#endif /* __WINE_SERVER__ */
|
||||
|
|
|
@ -112,10 +112,8 @@ extern void select_loop(void);
|
|||
|
||||
/* socket functions */
|
||||
|
||||
extern void server_init( int fd );
|
||||
extern int add_client( int client_fd, struct thread *self );
|
||||
extern void remove_client( int client_fd, int exit_code );
|
||||
extern int get_initial_client_fd(void);
|
||||
extern void set_timeout( int client_fd, struct timeval *when );
|
||||
extern int send_reply_v( int client_fd, int type, int pass_fd,
|
||||
struct iovec *vec, int veclen );
|
||||
|
|
|
@ -27,9 +27,11 @@ struct process_snapshot
|
|||
|
||||
/* process functions */
|
||||
|
||||
extern struct process *create_process(void);
|
||||
extern struct process *create_initial_process(void);
|
||||
extern struct process *create_process( struct new_process_request *req );
|
||||
extern struct process *get_process_from_id( void *id );
|
||||
extern struct process *get_process_from_handle( int handle, unsigned int access );
|
||||
extern int get_process_init_info( struct process *process, struct init_process_reply *reply );
|
||||
extern void add_process_thread( struct process *process,
|
||||
struct thread *thread );
|
||||
extern void remove_process_thread( struct process *process,
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
|
||||
enum request
|
||||
{
|
||||
REQ_NEW_PROCESS,
|
||||
REQ_NEW_THREAD,
|
||||
REQ_SET_DEBUG,
|
||||
REQ_INIT_PROCESS,
|
||||
REQ_INIT_THREAD,
|
||||
REQ_TERMINATE_PROCESS,
|
||||
REQ_TERMINATE_THREAD,
|
||||
|
@ -65,8 +67,10 @@ enum request
|
|||
#define DECL_HANDLER(name) \
|
||||
static void req_##name( struct name##_request *req, void *data, int len, int fd )
|
||||
|
||||
DECL_HANDLER(new_process);
|
||||
DECL_HANDLER(new_thread);
|
||||
DECL_HANDLER(set_debug);
|
||||
DECL_HANDLER(init_process);
|
||||
DECL_HANDLER(init_thread);
|
||||
DECL_HANDLER(terminate_process);
|
||||
DECL_HANDLER(terminate_thread);
|
||||
|
@ -122,8 +126,10 @@ static const struct handler {
|
|||
void (*handler)();
|
||||
unsigned int min_size;
|
||||
} req_handlers[REQ_NB_REQUESTS] = {
|
||||
{ (void(*)())req_new_process, sizeof(struct new_process_request) },
|
||||
{ (void(*)())req_new_thread, sizeof(struct new_thread_request) },
|
||||
{ (void(*)())req_set_debug, sizeof(struct set_debug_request) },
|
||||
{ (void(*)())req_init_process, sizeof(struct init_process_request) },
|
||||
{ (void(*)())req_init_thread, sizeof(struct init_thread_request) },
|
||||
{ (void(*)())req_terminate_process, sizeof(struct terminate_process_request) },
|
||||
{ (void(*)())req_terminate_thread, sizeof(struct terminate_thread_request) },
|
||||
|
|
|
@ -43,16 +43,14 @@ struct thread
|
|||
int affinity; /* affinity mask */
|
||||
int suspend; /* suspend count */
|
||||
enum request last_req; /* last request received (for debugging) */
|
||||
char *name;
|
||||
};
|
||||
|
||||
extern struct thread *current;
|
||||
|
||||
/* thread functions */
|
||||
|
||||
extern struct thread *create_thread( int fd, void *pid, int suspend,
|
||||
int thread_inherit, int process_inherit,
|
||||
int *thread_handle, int *process_handle );
|
||||
extern void create_initial_thread( int fd );
|
||||
extern struct thread *create_thread( int fd, void *pid, int suspend, int inherit, int *handle );
|
||||
extern struct thread *get_thread_from_id( void *id );
|
||||
extern struct thread *get_thread_from_handle( int handle, unsigned int access );
|
||||
extern void get_thread_info( struct thread *thread,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "server.h"
|
||||
#include "server/object.h"
|
||||
#include "server/thread.h"
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
|
@ -26,8 +27,7 @@ int main( int argc, char *argv[] )
|
|||
debug_level = 1;
|
||||
|
||||
if (debug_level) fprintf( stderr, "Server: starting (pid=%d)\n", getpid() );
|
||||
server_init( fd );
|
||||
select_loop();
|
||||
create_initial_thread( fd );
|
||||
if (debug_level) fprintf( stderr, "Server: exiting (pid=%d)\n", getpid() );
|
||||
exit(0);
|
||||
|
||||
|
|
113
server/process.c
113
server/process.c
|
@ -38,8 +38,7 @@ struct handle_entry
|
|||
unsigned int access;
|
||||
};
|
||||
|
||||
/* process structure; not much for now... */
|
||||
|
||||
/* process structure */
|
||||
struct process
|
||||
{
|
||||
struct object obj; /* object header */
|
||||
|
@ -57,10 +56,12 @@ struct process
|
|||
int affinity; /* process affinity mask */
|
||||
struct object *console_in; /* console input */
|
||||
struct object *console_out; /* console output */
|
||||
struct new_process_request *info; /* startup info (freed after startup) */
|
||||
};
|
||||
|
||||
static struct process *first_process;
|
||||
static struct process *initial_process;
|
||||
|
||||
static struct process initial_process;
|
||||
static struct process *first_process = &initial_process;
|
||||
static int running_processes;
|
||||
|
||||
#define MIN_HANDLE_ENTRIES 32
|
||||
|
@ -87,21 +88,12 @@ static const struct object_ops process_ops =
|
|||
process_destroy
|
||||
};
|
||||
|
||||
/* create a new process */
|
||||
struct process *create_process(void)
|
||||
|
||||
/* initialization of a process structure */
|
||||
static void init_process( struct process *process )
|
||||
{
|
||||
struct process *process, *parent;
|
||||
|
||||
if (!(process = mem_alloc( sizeof(*process) ))) return NULL;
|
||||
|
||||
parent = current ? current->process : NULL;
|
||||
if (!copy_handle_table( process, parent ))
|
||||
{
|
||||
free( process );
|
||||
return NULL;
|
||||
}
|
||||
init_object( &process->obj, &process_ops, NULL );
|
||||
process->next = first_process;
|
||||
process->next = NULL;
|
||||
process->prev = NULL;
|
||||
process->thread_list = NULL;
|
||||
process->exit_code = 0x103; /* STILL_ACTIVE */
|
||||
|
@ -110,24 +102,59 @@ struct process *create_process(void)
|
|||
process->affinity = 1;
|
||||
process->console_in = NULL;
|
||||
process->console_out = NULL;
|
||||
if (parent)
|
||||
{
|
||||
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 (first_process) first_process->prev = process;
|
||||
first_process = process;
|
||||
if (!initial_process)
|
||||
{
|
||||
initial_process = process;
|
||||
grab_object( initial_process ); /* so that we never free it */
|
||||
}
|
||||
|
||||
process->info = NULL;
|
||||
gettimeofday( &process->start_time, NULL );
|
||||
/* alloc a handle for the process itself */
|
||||
alloc_handle( process, process, PROCESS_ALL_ACCESS, 0 );
|
||||
}
|
||||
|
||||
/* create the initial process */
|
||||
struct process *create_initial_process(void)
|
||||
{
|
||||
copy_handle_table( &initial_process, NULL );
|
||||
init_process( &initial_process );
|
||||
grab_object( &initial_process ); /* so that we never free it */
|
||||
return &initial_process;
|
||||
|
||||
}
|
||||
|
||||
/* create a new process */
|
||||
struct process *create_process( struct new_process_request *req )
|
||||
{
|
||||
struct process *process = NULL;
|
||||
struct process *parent = current->process;
|
||||
|
||||
if (!(process = mem_alloc( sizeof(*process) ))) return NULL;
|
||||
if (!copy_handle_table( process, req->inherit_all ? parent : NULL ))
|
||||
{
|
||||
free( process );
|
||||
return NULL;
|
||||
}
|
||||
init_process( 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 (!(process->info = mem_alloc( sizeof(*process->info) ))) goto error;
|
||||
memcpy( process->info, req, sizeof(*req) );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
process->next = first_process;
|
||||
first_process->prev = process;
|
||||
first_process = process;
|
||||
return process;
|
||||
|
||||
error:
|
||||
release_object( process );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* destroy a process when its refcount is 0 */
|
||||
|
@ -135,7 +162,7 @@ static void process_destroy( struct object *obj )
|
|||
{
|
||||
struct process *process = (struct process *)obj;
|
||||
assert( obj->ops == &process_ops );
|
||||
assert( process != initial_process );
|
||||
assert( process != &initial_process );
|
||||
|
||||
/* we can't have a thread remaining */
|
||||
assert( !process->thread_list );
|
||||
|
@ -144,6 +171,7 @@ static void process_destroy( struct object *obj )
|
|||
else first_process = process->next;
|
||||
free_console( process );
|
||||
free_handles( process );
|
||||
if (process->info) free( process->info );
|
||||
if (debug_level) memset( process, 0xbb, sizeof(process) ); /* catch errors */
|
||||
free( process );
|
||||
}
|
||||
|
@ -163,6 +191,7 @@ static int process_signaled( struct object *obj, struct thread *thread )
|
|||
return !process->running_threads;
|
||||
}
|
||||
|
||||
|
||||
/* get a process from an id (and increment the refcount) */
|
||||
struct process *get_process_from_id( void *id )
|
||||
{
|
||||
|
@ -180,6 +209,20 @@ struct process *get_process_from_handle( int handle, unsigned int access )
|
|||
access, &process_ops );
|
||||
}
|
||||
|
||||
/* retrieve the initialization info for a new process */
|
||||
int get_process_init_info( struct process *process, struct init_process_reply *reply )
|
||||
{
|
||||
struct new_process_request *info;
|
||||
if (!(info = process->info)) return 0;
|
||||
process->info = NULL;
|
||||
reply->start_flags = info->start_flags;
|
||||
reply->hstdin = info->hstdin;
|
||||
reply->hstdout = info->hstdout;
|
||||
reply->hstderr = info->hstderr;
|
||||
free( info );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* a process has been killed (i.e. its last thread died) */
|
||||
static void process_killed( struct process *process, int exit_code )
|
||||
{
|
||||
|
@ -296,7 +339,7 @@ static struct handle_entry *get_handle( struct process *process, int handle )
|
|||
if (HANDLE_IS_GLOBAL(handle))
|
||||
{
|
||||
handle = HANDLE_GLOBAL_TO_LOCAL(handle);
|
||||
process = initial_process;
|
||||
process = &initial_process;
|
||||
}
|
||||
handle--; /* handles start at 1 */
|
||||
if ((handle < 0) || (handle > process->handle_last)) goto error;
|
||||
|
@ -383,7 +426,7 @@ int close_handle( struct process *process, int handle )
|
|||
if (HANDLE_IS_GLOBAL(handle))
|
||||
{
|
||||
handle = HANDLE_GLOBAL_TO_LOCAL(handle);
|
||||
process = initial_process;
|
||||
process = &initial_process;
|
||||
}
|
||||
if (!(entry = get_handle( process, handle ))) return 0;
|
||||
if (entry->access & RESERVED_CLOSE_PROTECT) return 0; /* FIXME: error code */
|
||||
|
@ -449,7 +492,7 @@ int duplicate_handle( struct process *src, int src_handle, struct process *dst,
|
|||
if (!entry) return -1;
|
||||
|
||||
if (options & DUP_HANDLE_SAME_ACCESS) access = entry->access;
|
||||
if (options & DUP_HANDLE_MAKE_GLOBAL) dst = initial_process;
|
||||
if (options & DUP_HANDLE_MAKE_GLOBAL) dst = &initial_process;
|
||||
access &= ~RESERVED_ALL;
|
||||
res = alloc_handle( dst, entry->ptr, access, inherit );
|
||||
if (options & DUP_HANDLE_MAKE_GLOBAL) res = HANDLE_LOCAL_TO_GLOBAL(res);
|
||||
|
|
|
@ -101,46 +101,63 @@ void call_kill_handler( struct thread *thread, int exit_code )
|
|||
}
|
||||
|
||||
|
||||
/* create a new process */
|
||||
DECL_HANDLER(new_process)
|
||||
{
|
||||
struct new_process_reply reply;
|
||||
struct process *process;
|
||||
|
||||
if ((process = create_process( req )))
|
||||
{
|
||||
reply.pid = process;
|
||||
reply.handle = alloc_handle( current->process, process,
|
||||
PROCESS_ALL_ACCESS, req->inherit );
|
||||
release_object( process );
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.handle = -1;
|
||||
reply.pid = NULL;
|
||||
}
|
||||
send_reply( current, -1, 1, &reply, sizeof(reply) );
|
||||
}
|
||||
|
||||
/* create a new thread */
|
||||
DECL_HANDLER(new_thread)
|
||||
{
|
||||
struct new_thread_reply reply;
|
||||
struct thread *new_thread;
|
||||
int new_fd, err;
|
||||
int new_fd;
|
||||
|
||||
if ((new_fd = dup(fd)) == -1)
|
||||
if ((new_fd = dup(fd)) != -1)
|
||||
{
|
||||
new_thread = NULL;
|
||||
err = ERROR_TOO_MANY_OPEN_FILES;
|
||||
goto done;
|
||||
}
|
||||
if (!(new_thread = create_thread( new_fd, req->pid, req->suspend,
|
||||
req->tinherit, req->pinherit,
|
||||
&reply.thandle, &reply.phandle )))
|
||||
{
|
||||
close( new_fd );
|
||||
err = ERROR_OUTOFMEMORY;
|
||||
goto done;
|
||||
}
|
||||
reply.tid = new_thread;
|
||||
reply.pid = new_thread->process;
|
||||
err = ERROR_SUCCESS;
|
||||
|
||||
done:
|
||||
if (!current)
|
||||
{
|
||||
/* first client doesn't have a current */
|
||||
struct iovec vec = { &reply, sizeof(reply) };
|
||||
send_reply_v( get_initial_client_fd(), err, -1, &vec, 1 );
|
||||
reply.tid = create_thread( new_fd, req->pid, req->suspend,
|
||||
req->inherit, &reply.handle );
|
||||
if (!reply.tid) close( new_fd );
|
||||
}
|
||||
else
|
||||
{
|
||||
SET_ERROR( err );
|
||||
send_reply( current, -1, 1, &reply, sizeof(reply) );
|
||||
}
|
||||
SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
|
||||
|
||||
send_reply( current, -1, 1, &reply, sizeof(reply) );
|
||||
}
|
||||
|
||||
/* create a new thread */
|
||||
/* initialize a new process */
|
||||
DECL_HANDLER(init_process)
|
||||
{
|
||||
struct init_process_reply reply;
|
||||
if (current->state != RUNNING)
|
||||
{
|
||||
fatal_protocol_error( "init_process: init_thread not called yet\n" );
|
||||
return;
|
||||
}
|
||||
if (!get_process_init_info( current->process, &reply ))
|
||||
{
|
||||
fatal_protocol_error( "init_process: called twice\n" );
|
||||
return;
|
||||
}
|
||||
send_reply( current, -1, 1, &reply, sizeof(reply) );
|
||||
}
|
||||
|
||||
/* initialize a new thread */
|
||||
DECL_HANDLER(init_thread)
|
||||
{
|
||||
if (current->state != STARTING)
|
||||
|
@ -150,12 +167,7 @@ DECL_HANDLER(init_thread)
|
|||
}
|
||||
current->state = RUNNING;
|
||||
current->unix_pid = req->unix_pid;
|
||||
if (!(current->name = mem_alloc( len + 1 ))) goto done;
|
||||
memcpy( current->name, data, len );
|
||||
current->name[len] = '\0';
|
||||
CLEAR_ERROR();
|
||||
done:
|
||||
if (current->suspend > 0 && current->unix_pid)
|
||||
if (current->suspend > 0)
|
||||
kill( current->unix_pid, SIGSTOP );
|
||||
send_reply( current, -1, 0 );
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ struct client
|
|||
struct thread *self; /* client thread (opaque pointer) */
|
||||
};
|
||||
|
||||
static int initial_client_fd; /* fd of the first client */
|
||||
|
||||
/* exit code passed to remove_client */
|
||||
#define OUT_OF_MEMORY -1
|
||||
|
@ -258,15 +257,6 @@ static const struct select_ops client_ops =
|
|||
/*******************************************************************/
|
||||
/* server-side exported functions */
|
||||
|
||||
/* server initialization */
|
||||
void server_init( int fd )
|
||||
{
|
||||
/* special magic to create the initial thread */
|
||||
initial_client_fd = fd;
|
||||
add_client( initial_client_fd, NULL );
|
||||
}
|
||||
|
||||
|
||||
/* add a client */
|
||||
int add_client( int client_fd, struct thread *self )
|
||||
{
|
||||
|
@ -299,7 +289,6 @@ void remove_client( int client_fd, int exit_code )
|
|||
call_kill_handler( client->self, exit_code );
|
||||
|
||||
remove_select_user( client_fd );
|
||||
if (initial_client_fd == client_fd) initial_client_fd = -1;
|
||||
close( client_fd );
|
||||
|
||||
/* Purge messages */
|
||||
|
@ -308,13 +297,6 @@ void remove_client( int client_fd, int exit_code )
|
|||
free( client );
|
||||
}
|
||||
|
||||
/* return the fd of the initial client */
|
||||
int get_initial_client_fd(void)
|
||||
{
|
||||
assert( initial_client_fd != -1 );
|
||||
return initial_client_fd;
|
||||
}
|
||||
|
||||
/* send a reply to a client */
|
||||
int send_reply_v( int client_fd, int type, int pass_fd,
|
||||
struct iovec *vec, int veclen )
|
||||
|
|
|
@ -71,32 +71,15 @@ static const struct object_ops thread_ops =
|
|||
destroy_thread
|
||||
};
|
||||
|
||||
static struct thread *first_thread;
|
||||
static struct thread initial_thread;
|
||||
static struct thread *first_thread = &initial_thread;
|
||||
|
||||
|
||||
/* create a new thread */
|
||||
struct thread *create_thread( int fd, void *pid, int suspend,
|
||||
int thread_inherit, int process_inherit,
|
||||
int *thread_handle, int *process_handle )
|
||||
/* initialization of a thread structure */
|
||||
static void init_thread( struct thread *thread, int fd )
|
||||
{
|
||||
struct thread *thread;
|
||||
struct process *process;
|
||||
|
||||
if (!(thread = mem_alloc( sizeof(*thread) ))) return NULL;
|
||||
|
||||
if (pid) process = get_process_from_id( pid );
|
||||
else process = create_process();
|
||||
if (!process)
|
||||
{
|
||||
free( thread );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
init_object( &thread->obj, &thread_ops, NULL );
|
||||
thread->client_fd = fd;
|
||||
thread->process = process;
|
||||
thread->unix_pid = 0; /* not known yet */
|
||||
thread->name = NULL;
|
||||
thread->mutex = NULL;
|
||||
thread->wait = NULL;
|
||||
thread->apc = NULL;
|
||||
|
@ -104,40 +87,58 @@ struct thread *create_thread( int fd, void *pid, int suspend,
|
|||
thread->error = 0;
|
||||
thread->state = STARTING;
|
||||
thread->exit_code = 0x103; /* STILL_ACTIVE */
|
||||
thread->next = first_thread;
|
||||
thread->next = NULL;
|
||||
thread->prev = NULL;
|
||||
thread->priority = THREAD_PRIORITY_NORMAL;
|
||||
thread->affinity = 1;
|
||||
thread->suspend = suspend? 1 : 0;
|
||||
thread->suspend = 0;
|
||||
}
|
||||
|
||||
if (first_thread) first_thread->prev = thread;
|
||||
/* create the initial thread and start the main server loop */
|
||||
void create_initial_thread( int fd )
|
||||
{
|
||||
current = &initial_thread;
|
||||
init_thread( &initial_thread, fd );
|
||||
initial_thread.process = create_initial_process();
|
||||
add_process_thread( initial_thread.process, &initial_thread );
|
||||
add_client( fd, &initial_thread );
|
||||
select_loop();
|
||||
}
|
||||
|
||||
/* create a new thread */
|
||||
struct thread *create_thread( int fd, void *pid, int suspend, int inherit, int *handle )
|
||||
{
|
||||
struct thread *thread;
|
||||
struct process *process;
|
||||
|
||||
if (!(thread = mem_alloc( sizeof(*thread) ))) return NULL;
|
||||
|
||||
if (!(process = get_process_from_id( pid )))
|
||||
{
|
||||
free( thread );
|
||||
return NULL;
|
||||
}
|
||||
init_thread( thread, fd );
|
||||
thread->process = process;
|
||||
|
||||
if (suspend) thread->suspend++;
|
||||
|
||||
thread->next = first_thread;
|
||||
first_thread->prev = thread;
|
||||
first_thread = thread;
|
||||
add_process_thread( process, thread );
|
||||
|
||||
*thread_handle = *process_handle = -1;
|
||||
if (current)
|
||||
if ((*handle = alloc_handle( current->process, thread,
|
||||
THREAD_ALL_ACCESS, inherit )) == -1) goto error;
|
||||
if (add_client( fd, thread ) == -1)
|
||||
{
|
||||
if ((*thread_handle = alloc_handle( current->process, thread,
|
||||
THREAD_ALL_ACCESS, thread_inherit )) == -1)
|
||||
goto error;
|
||||
SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
|
||||
goto error;
|
||||
}
|
||||
if (current && !pid)
|
||||
{
|
||||
if ((*process_handle = alloc_handle( current->process, process,
|
||||
PROCESS_ALL_ACCESS, process_inherit )) == -1)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (add_client( fd, thread ) == -1) goto error;
|
||||
|
||||
return thread;
|
||||
|
||||
error:
|
||||
if (current)
|
||||
{
|
||||
close_handle( current->process, *thread_handle );
|
||||
close_handle( current->process, *process_handle );
|
||||
}
|
||||
if (current) close_handle( current->process, *handle );
|
||||
remove_process_thread( process, thread );
|
||||
release_object( thread );
|
||||
return NULL;
|
||||
|
@ -153,7 +154,6 @@ static void destroy_thread( struct object *obj )
|
|||
if (thread->next) thread->next->prev = thread->prev;
|
||||
if (thread->prev) thread->prev->next = thread->next;
|
||||
else first_thread = thread->next;
|
||||
if (thread->name) free( thread->name );
|
||||
if (thread->apc) free( thread->apc );
|
||||
if (debug_level) memset( thread, 0xaa, sizeof(thread) ); /* catch errors */
|
||||
free( thread );
|
||||
|
@ -165,8 +165,8 @@ static void dump_thread( struct object *obj, int verbose )
|
|||
struct thread *thread = (struct thread *)obj;
|
||||
assert( obj->ops == &thread_ops );
|
||||
|
||||
fprintf( stderr, "Thread pid=%d fd=%d name='%s'\n",
|
||||
thread->unix_pid, thread->client_fd, thread->name );
|
||||
fprintf( stderr, "Thread pid=%d fd=%d\n",
|
||||
thread->unix_pid, thread->client_fd );
|
||||
}
|
||||
|
||||
static int thread_signaled( struct object *obj, struct thread *thread )
|
||||
|
@ -195,7 +195,7 @@ struct thread *get_thread_from_handle( int handle, unsigned int access )
|
|||
void get_thread_info( struct thread *thread,
|
||||
struct get_thread_info_reply *reply )
|
||||
{
|
||||
reply->pid = thread;
|
||||
reply->tid = thread;
|
||||
reply->exit_code = thread->exit_code;
|
||||
reply->priority = thread->priority;
|
||||
}
|
||||
|
|
|
@ -6,21 +6,36 @@
|
|||
#include "server.h"
|
||||
#include "server/thread.h"
|
||||
|
||||
static int dump_new_process_request( struct new_process_request *req, int len )
|
||||
{
|
||||
fprintf( stderr, " inherit=%d,", req->inherit );
|
||||
fprintf( stderr, " inherit_all=%d,", req->inherit_all );
|
||||
fprintf( stderr, " start_flags=%d,", req->start_flags );
|
||||
fprintf( stderr, " hstdin=%d,", req->hstdin );
|
||||
fprintf( stderr, " hstdout=%d,", req->hstdout );
|
||||
fprintf( stderr, " hstderr=%d", req->hstderr );
|
||||
return (int)sizeof(*req);
|
||||
}
|
||||
|
||||
static int dump_new_process_reply( struct new_process_reply *req, int len )
|
||||
{
|
||||
fprintf( stderr, " pid=%p,", req->pid );
|
||||
fprintf( stderr, " handle=%d", req->handle );
|
||||
return (int)sizeof(*req);
|
||||
}
|
||||
|
||||
static int dump_new_thread_request( struct new_thread_request *req, int len )
|
||||
{
|
||||
fprintf( stderr, " pid=%p,", req->pid );
|
||||
fprintf( stderr, " suspend=%d,", req->suspend );
|
||||
fprintf( stderr, " tinherit=%d,", req->tinherit );
|
||||
fprintf( stderr, " pinherit=%d", req->pinherit );
|
||||
fprintf( stderr, " inherit=%d", req->inherit );
|
||||
return (int)sizeof(*req);
|
||||
}
|
||||
|
||||
static int dump_new_thread_reply( struct new_thread_reply *req, int len )
|
||||
{
|
||||
fprintf( stderr, " tid=%p,", req->tid );
|
||||
fprintf( stderr, " thandle=%d,", req->thandle );
|
||||
fprintf( stderr, " pid=%p,", req->pid );
|
||||
fprintf( stderr, " phandle=%d", req->phandle );
|
||||
fprintf( stderr, " handle=%d", req->handle );
|
||||
return (int)sizeof(*req);
|
||||
}
|
||||
|
||||
|
@ -30,11 +45,25 @@ static int dump_set_debug_request( struct set_debug_request *req, int len )
|
|||
return (int)sizeof(*req);
|
||||
}
|
||||
|
||||
static int dump_init_process_request( struct init_process_request *req, int len )
|
||||
{
|
||||
fprintf( stderr, " dummy=%d", req->dummy );
|
||||
return (int)sizeof(*req);
|
||||
}
|
||||
|
||||
static int dump_init_process_reply( struct init_process_reply *req, int len )
|
||||
{
|
||||
fprintf( stderr, " start_flags=%d,", req->start_flags );
|
||||
fprintf( stderr, " hstdin=%d,", req->hstdin );
|
||||
fprintf( stderr, " hstdout=%d,", req->hstdout );
|
||||
fprintf( stderr, " hstderr=%d", req->hstderr );
|
||||
return (int)sizeof(*req);
|
||||
}
|
||||
|
||||
static int dump_init_thread_request( struct init_thread_request *req, int len )
|
||||
{
|
||||
fprintf( stderr, " unix_pid=%d,", req->unix_pid );
|
||||
fprintf( stderr, " cmd_line=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) );
|
||||
return len;
|
||||
fprintf( stderr, " unix_pid=%d", req->unix_pid );
|
||||
return (int)sizeof(*req);
|
||||
}
|
||||
|
||||
static int dump_terminate_process_request( struct terminate_process_request *req, int len )
|
||||
|
@ -84,7 +113,7 @@ static int dump_get_thread_info_request( struct get_thread_info_request *req, in
|
|||
|
||||
static int dump_get_thread_info_reply( struct get_thread_info_reply *req, int len )
|
||||
{
|
||||
fprintf( stderr, " pid=%p,", req->pid );
|
||||
fprintf( stderr, " tid=%p,", req->tid );
|
||||
fprintf( stderr, " exit_code=%d,", req->exit_code );
|
||||
fprintf( stderr, " priority=%d", req->priority );
|
||||
return (int)sizeof(*req);
|
||||
|
@ -600,10 +629,14 @@ struct dumper
|
|||
|
||||
static const struct dumper dumpers[REQ_NB_REQUESTS] =
|
||||
{
|
||||
{ (int(*)(void *,int))dump_new_process_request,
|
||||
(void(*)())dump_new_process_reply },
|
||||
{ (int(*)(void *,int))dump_new_thread_request,
|
||||
(void(*)())dump_new_thread_reply },
|
||||
{ (int(*)(void *,int))dump_set_debug_request,
|
||||
(void(*)())0 },
|
||||
{ (int(*)(void *,int))dump_init_process_request,
|
||||
(void(*)())dump_init_process_reply },
|
||||
{ (int(*)(void *,int))dump_init_thread_request,
|
||||
(void(*)())0 },
|
||||
{ (int(*)(void *,int))dump_terminate_process_request,
|
||||
|
@ -708,8 +741,10 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] =
|
|||
|
||||
static const char * const req_names[REQ_NB_REQUESTS] =
|
||||
{
|
||||
"new_process",
|
||||
"new_thread",
|
||||
"set_debug",
|
||||
"init_process",
|
||||
"init_thread",
|
||||
"terminate_process",
|
||||
"terminate_thread",
|
||||
|
|
Loading…
Reference in New Issue