forked from Mirrors/wine-wine
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.oldstable
parent
4f278bdac1
commit
f692d44607
|
@ -40,20 +40,34 @@ struct cmsg_fd
|
||||||
/* which case it isn't necessary to define a structure. */
|
/* 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 */
|
/* Create a new thread from the context of the parent */
|
||||||
struct new_thread_request
|
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 suspend; /* new thread should be suspended on creation */
|
||||||
int tinherit; /* inherit flag for thread handle */
|
int inherit; /* inherit flag */
|
||||||
int pinherit; /* inherit flag for process handle */
|
|
||||||
};
|
};
|
||||||
struct new_thread_reply
|
struct new_thread_reply
|
||||||
{
|
{
|
||||||
void* tid; /* thread id */
|
void* tid; /* thread id */
|
||||||
int thandle; /* thread handle (in the current process) */
|
int handle; /* thread handle (in the current process) */
|
||||||
void* pid; /* process id (created if necessary) */
|
|
||||||
int phandle; /* process 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() */
|
/* Initialize a thread; called from the child after fork()/clone() */
|
||||||
struct init_thread_request
|
struct init_thread_request
|
||||||
{
|
{
|
||||||
int unix_pid; /* Unix pid of new thread */
|
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
|
struct get_thread_info_reply
|
||||||
{
|
{
|
||||||
void* pid; /* server thread id */
|
void* tid; /* server thread id */
|
||||||
int exit_code; /* thread exit code */
|
int exit_code; /* thread exit code */
|
||||||
int priority; /* thread priority level */
|
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,
|
extern unsigned int CLIENT_WaitReply( int *len, int *passed_fd,
|
||||||
int n, ... /* arg_1, len_1, etc. */ );
|
int n, ... /* arg_1, len_1, etc. */ );
|
||||||
extern unsigned int CLIENT_WaitSimpleReply( void *reply, int len, int *passed_fd );
|
extern unsigned int CLIENT_WaitSimpleReply( void *reply, int len, int *passed_fd );
|
||||||
|
extern int CLIENT_InitServer(void);
|
||||||
|
|
||||||
struct _THDB;
|
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_SetDebug( int level );
|
||||||
extern int CLIENT_InitThread(void);
|
extern int CLIENT_InitThread(void);
|
||||||
#endif /* __WINE_SERVER__ */
|
#endif /* __WINE_SERVER__ */
|
||||||
|
|
|
@ -112,10 +112,8 @@ extern void select_loop(void);
|
||||||
|
|
||||||
/* socket functions */
|
/* socket functions */
|
||||||
|
|
||||||
extern void server_init( int fd );
|
|
||||||
extern int add_client( int client_fd, struct thread *self );
|
extern int add_client( int client_fd, struct thread *self );
|
||||||
extern void remove_client( int client_fd, int exit_code );
|
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 void set_timeout( int client_fd, struct timeval *when );
|
||||||
extern int send_reply_v( int client_fd, int type, int pass_fd,
|
extern int send_reply_v( int client_fd, int type, int pass_fd,
|
||||||
struct iovec *vec, int veclen );
|
struct iovec *vec, int veclen );
|
||||||
|
|
|
@ -27,9 +27,11 @@ struct process_snapshot
|
||||||
|
|
||||||
/* process functions */
|
/* 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_id( void *id );
|
||||||
extern struct process *get_process_from_handle( int handle, unsigned int access );
|
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,
|
extern void add_process_thread( struct process *process,
|
||||||
struct thread *thread );
|
struct thread *thread );
|
||||||
extern void remove_process_thread( struct process *process,
|
extern void remove_process_thread( struct process *process,
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
|
|
||||||
enum request
|
enum request
|
||||||
{
|
{
|
||||||
|
REQ_NEW_PROCESS,
|
||||||
REQ_NEW_THREAD,
|
REQ_NEW_THREAD,
|
||||||
REQ_SET_DEBUG,
|
REQ_SET_DEBUG,
|
||||||
|
REQ_INIT_PROCESS,
|
||||||
REQ_INIT_THREAD,
|
REQ_INIT_THREAD,
|
||||||
REQ_TERMINATE_PROCESS,
|
REQ_TERMINATE_PROCESS,
|
||||||
REQ_TERMINATE_THREAD,
|
REQ_TERMINATE_THREAD,
|
||||||
|
@ -65,8 +67,10 @@ enum request
|
||||||
#define DECL_HANDLER(name) \
|
#define DECL_HANDLER(name) \
|
||||||
static void req_##name( struct name##_request *req, void *data, int len, int fd )
|
static void req_##name( struct name##_request *req, void *data, int len, int fd )
|
||||||
|
|
||||||
|
DECL_HANDLER(new_process);
|
||||||
DECL_HANDLER(new_thread);
|
DECL_HANDLER(new_thread);
|
||||||
DECL_HANDLER(set_debug);
|
DECL_HANDLER(set_debug);
|
||||||
|
DECL_HANDLER(init_process);
|
||||||
DECL_HANDLER(init_thread);
|
DECL_HANDLER(init_thread);
|
||||||
DECL_HANDLER(terminate_process);
|
DECL_HANDLER(terminate_process);
|
||||||
DECL_HANDLER(terminate_thread);
|
DECL_HANDLER(terminate_thread);
|
||||||
|
@ -122,8 +126,10 @@ static const struct handler {
|
||||||
void (*handler)();
|
void (*handler)();
|
||||||
unsigned int min_size;
|
unsigned int min_size;
|
||||||
} req_handlers[REQ_NB_REQUESTS] = {
|
} 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_new_thread, sizeof(struct new_thread_request) },
|
||||||
{ (void(*)())req_set_debug, sizeof(struct set_debug_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_init_thread, sizeof(struct init_thread_request) },
|
||||||
{ (void(*)())req_terminate_process, sizeof(struct terminate_process_request) },
|
{ (void(*)())req_terminate_process, sizeof(struct terminate_process_request) },
|
||||||
{ (void(*)())req_terminate_thread, sizeof(struct terminate_thread_request) },
|
{ (void(*)())req_terminate_thread, sizeof(struct terminate_thread_request) },
|
||||||
|
|
|
@ -43,16 +43,14 @@ struct thread
|
||||||
int affinity; /* affinity mask */
|
int affinity; /* affinity mask */
|
||||||
int suspend; /* suspend count */
|
int suspend; /* suspend count */
|
||||||
enum request last_req; /* last request received (for debugging) */
|
enum request last_req; /* last request received (for debugging) */
|
||||||
char *name;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct thread *current;
|
extern struct thread *current;
|
||||||
|
|
||||||
/* thread functions */
|
/* thread functions */
|
||||||
|
|
||||||
extern struct thread *create_thread( int fd, void *pid, int suspend,
|
extern void create_initial_thread( int fd );
|
||||||
int thread_inherit, int process_inherit,
|
extern struct thread *create_thread( int fd, void *pid, int suspend, int inherit, int *handle );
|
||||||
int *thread_handle, int *process_handle );
|
|
||||||
extern struct thread *get_thread_from_id( void *id );
|
extern struct thread *get_thread_from_id( void *id );
|
||||||
extern struct thread *get_thread_from_handle( int handle, unsigned int access );
|
extern struct thread *get_thread_from_handle( int handle, unsigned int access );
|
||||||
extern void get_thread_info( struct thread *thread,
|
extern void get_thread_info( struct thread *thread,
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "server/object.h"
|
#include "server/object.h"
|
||||||
|
#include "server/thread.h"
|
||||||
|
|
||||||
int main( int argc, char *argv[] )
|
int main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
|
@ -26,8 +27,7 @@ int main( int argc, char *argv[] )
|
||||||
debug_level = 1;
|
debug_level = 1;
|
||||||
|
|
||||||
if (debug_level) fprintf( stderr, "Server: starting (pid=%d)\n", getpid() );
|
if (debug_level) fprintf( stderr, "Server: starting (pid=%d)\n", getpid() );
|
||||||
server_init( fd );
|
create_initial_thread( fd );
|
||||||
select_loop();
|
|
||||||
if (debug_level) fprintf( stderr, "Server: exiting (pid=%d)\n", getpid() );
|
if (debug_level) fprintf( stderr, "Server: exiting (pid=%d)\n", getpid() );
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
|
|
113
server/process.c
113
server/process.c
|
@ -38,8 +38,7 @@ struct handle_entry
|
||||||
unsigned int access;
|
unsigned int access;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* process structure; not much for now... */
|
/* process structure */
|
||||||
|
|
||||||
struct process
|
struct process
|
||||||
{
|
{
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
|
@ -57,10 +56,12 @@ struct process
|
||||||
int affinity; /* process affinity mask */
|
int affinity; /* process affinity mask */
|
||||||
struct object *console_in; /* console input */
|
struct object *console_in; /* console input */
|
||||||
struct object *console_out; /* console output */
|
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;
|
static int running_processes;
|
||||||
|
|
||||||
#define MIN_HANDLE_ENTRIES 32
|
#define MIN_HANDLE_ENTRIES 32
|
||||||
|
@ -87,21 +88,12 @@ static const struct object_ops process_ops =
|
||||||
process_destroy
|
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 );
|
init_object( &process->obj, &process_ops, NULL );
|
||||||
process->next = first_process;
|
process->next = NULL;
|
||||||
process->prev = NULL;
|
process->prev = NULL;
|
||||||
process->thread_list = NULL;
|
process->thread_list = NULL;
|
||||||
process->exit_code = 0x103; /* STILL_ACTIVE */
|
process->exit_code = 0x103; /* STILL_ACTIVE */
|
||||||
|
@ -110,24 +102,59 @@ struct process *create_process(void)
|
||||||
process->affinity = 1;
|
process->affinity = 1;
|
||||||
process->console_in = NULL;
|
process->console_in = NULL;
|
||||||
process->console_out = NULL;
|
process->console_out = NULL;
|
||||||
if (parent)
|
process->info = NULL;
|
||||||
{
|
|
||||||
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 */
|
|
||||||
}
|
|
||||||
|
|
||||||
gettimeofday( &process->start_time, NULL );
|
gettimeofday( &process->start_time, NULL );
|
||||||
/* alloc a handle for the process itself */
|
/* alloc a handle for the process itself */
|
||||||
alloc_handle( process, process, PROCESS_ALL_ACCESS, 0 );
|
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;
|
return process;
|
||||||
|
|
||||||
|
error:
|
||||||
|
release_object( process );
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* destroy a process when its refcount is 0 */
|
/* 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;
|
struct process *process = (struct process *)obj;
|
||||||
assert( obj->ops == &process_ops );
|
assert( obj->ops == &process_ops );
|
||||||
assert( process != initial_process );
|
assert( process != &initial_process );
|
||||||
|
|
||||||
/* we can't have a thread remaining */
|
/* we can't have a thread remaining */
|
||||||
assert( !process->thread_list );
|
assert( !process->thread_list );
|
||||||
|
@ -144,6 +171,7 @@ static void process_destroy( struct object *obj )
|
||||||
else first_process = process->next;
|
else first_process = process->next;
|
||||||
free_console( process );
|
free_console( process );
|
||||||
free_handles( process );
|
free_handles( process );
|
||||||
|
if (process->info) free( process->info );
|
||||||
if (debug_level) memset( process, 0xbb, sizeof(process) ); /* catch errors */
|
if (debug_level) memset( process, 0xbb, sizeof(process) ); /* catch errors */
|
||||||
free( process );
|
free( process );
|
||||||
}
|
}
|
||||||
|
@ -163,6 +191,7 @@ static int process_signaled( struct object *obj, struct thread *thread )
|
||||||
return !process->running_threads;
|
return !process->running_threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* get a process from an id (and increment the refcount) */
|
/* get a process from an id (and increment the refcount) */
|
||||||
struct process *get_process_from_id( void *id )
|
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 );
|
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) */
|
/* a process has been killed (i.e. its last thread died) */
|
||||||
static void process_killed( struct process *process, int exit_code )
|
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))
|
if (HANDLE_IS_GLOBAL(handle))
|
||||||
{
|
{
|
||||||
handle = HANDLE_GLOBAL_TO_LOCAL(handle);
|
handle = HANDLE_GLOBAL_TO_LOCAL(handle);
|
||||||
process = initial_process;
|
process = &initial_process;
|
||||||
}
|
}
|
||||||
handle--; /* handles start at 1 */
|
handle--; /* handles start at 1 */
|
||||||
if ((handle < 0) || (handle > process->handle_last)) goto error;
|
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))
|
if (HANDLE_IS_GLOBAL(handle))
|
||||||
{
|
{
|
||||||
handle = HANDLE_GLOBAL_TO_LOCAL(handle);
|
handle = HANDLE_GLOBAL_TO_LOCAL(handle);
|
||||||
process = initial_process;
|
process = &initial_process;
|
||||||
}
|
}
|
||||||
if (!(entry = get_handle( process, handle ))) return 0;
|
if (!(entry = get_handle( process, handle ))) return 0;
|
||||||
if (entry->access & RESERVED_CLOSE_PROTECT) return 0; /* FIXME: error code */
|
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 (!entry) return -1;
|
||||||
|
|
||||||
if (options & DUP_HANDLE_SAME_ACCESS) access = entry->access;
|
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;
|
access &= ~RESERVED_ALL;
|
||||||
res = alloc_handle( dst, entry->ptr, access, inherit );
|
res = alloc_handle( dst, entry->ptr, access, inherit );
|
||||||
if (options & DUP_HANDLE_MAKE_GLOBAL) res = HANDLE_LOCAL_TO_GLOBAL(res);
|
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 */
|
/* create a new thread */
|
||||||
DECL_HANDLER(new_thread)
|
DECL_HANDLER(new_thread)
|
||||||
{
|
{
|
||||||
struct new_thread_reply reply;
|
struct new_thread_reply reply;
|
||||||
struct thread *new_thread;
|
int new_fd;
|
||||||
int new_fd, err;
|
|
||||||
|
|
||||||
if ((new_fd = dup(fd)) == -1)
|
if ((new_fd = dup(fd)) != -1)
|
||||||
{
|
{
|
||||||
new_thread = NULL;
|
reply.tid = create_thread( new_fd, req->pid, req->suspend,
|
||||||
err = ERROR_TOO_MANY_OPEN_FILES;
|
req->inherit, &reply.handle );
|
||||||
goto done;
|
if (!reply.tid) close( new_fd );
|
||||||
}
|
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
|
||||||
SET_ERROR( err );
|
|
||||||
send_reply( current, -1, 1, &reply, sizeof(reply) );
|
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)
|
DECL_HANDLER(init_thread)
|
||||||
{
|
{
|
||||||
if (current->state != STARTING)
|
if (current->state != STARTING)
|
||||||
|
@ -150,12 +167,7 @@ DECL_HANDLER(init_thread)
|
||||||
}
|
}
|
||||||
current->state = RUNNING;
|
current->state = RUNNING;
|
||||||
current->unix_pid = req->unix_pid;
|
current->unix_pid = req->unix_pid;
|
||||||
if (!(current->name = mem_alloc( len + 1 ))) goto done;
|
if (current->suspend > 0)
|
||||||
memcpy( current->name, data, len );
|
|
||||||
current->name[len] = '\0';
|
|
||||||
CLEAR_ERROR();
|
|
||||||
done:
|
|
||||||
if (current->suspend > 0 && current->unix_pid)
|
|
||||||
kill( current->unix_pid, SIGSTOP );
|
kill( current->unix_pid, SIGSTOP );
|
||||||
send_reply( current, -1, 0 );
|
send_reply( current, -1, 0 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ struct client
|
||||||
struct thread *self; /* client thread (opaque pointer) */
|
struct thread *self; /* client thread (opaque pointer) */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int initial_client_fd; /* fd of the first client */
|
|
||||||
|
|
||||||
/* exit code passed to remove_client */
|
/* exit code passed to remove_client */
|
||||||
#define OUT_OF_MEMORY -1
|
#define OUT_OF_MEMORY -1
|
||||||
|
@ -258,15 +257,6 @@ static const struct select_ops client_ops =
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
/* server-side exported functions */
|
/* 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 */
|
/* add a client */
|
||||||
int add_client( int client_fd, struct thread *self )
|
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 );
|
call_kill_handler( client->self, exit_code );
|
||||||
|
|
||||||
remove_select_user( client_fd );
|
remove_select_user( client_fd );
|
||||||
if (initial_client_fd == client_fd) initial_client_fd = -1;
|
|
||||||
close( client_fd );
|
close( client_fd );
|
||||||
|
|
||||||
/* Purge messages */
|
/* Purge messages */
|
||||||
|
@ -308,13 +297,6 @@ void remove_client( int client_fd, int exit_code )
|
||||||
free( client );
|
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 */
|
/* send a reply to a client */
|
||||||
int send_reply_v( int client_fd, int type, int pass_fd,
|
int send_reply_v( int client_fd, int type, int pass_fd,
|
||||||
struct iovec *vec, int veclen )
|
struct iovec *vec, int veclen )
|
||||||
|
|
|
@ -71,32 +71,15 @@ static const struct object_ops thread_ops =
|
||||||
destroy_thread
|
destroy_thread
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct thread *first_thread;
|
static struct thread initial_thread;
|
||||||
|
static struct thread *first_thread = &initial_thread;
|
||||||
|
|
||||||
|
/* initialization of a thread structure */
|
||||||
/* create a new thread */
|
static void init_thread( struct thread *thread, int fd )
|
||||||
struct thread *create_thread( int fd, void *pid, int suspend,
|
|
||||||
int thread_inherit, int process_inherit,
|
|
||||||
int *thread_handle, int *process_handle )
|
|
||||||
{
|
{
|
||||||
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 );
|
init_object( &thread->obj, &thread_ops, NULL );
|
||||||
thread->client_fd = fd;
|
thread->client_fd = fd;
|
||||||
thread->process = process;
|
|
||||||
thread->unix_pid = 0; /* not known yet */
|
thread->unix_pid = 0; /* not known yet */
|
||||||
thread->name = NULL;
|
|
||||||
thread->mutex = NULL;
|
thread->mutex = NULL;
|
||||||
thread->wait = NULL;
|
thread->wait = NULL;
|
||||||
thread->apc = NULL;
|
thread->apc = NULL;
|
||||||
|
@ -104,40 +87,58 @@ struct thread *create_thread( int fd, void *pid, int suspend,
|
||||||
thread->error = 0;
|
thread->error = 0;
|
||||||
thread->state = STARTING;
|
thread->state = STARTING;
|
||||||
thread->exit_code = 0x103; /* STILL_ACTIVE */
|
thread->exit_code = 0x103; /* STILL_ACTIVE */
|
||||||
thread->next = first_thread;
|
thread->next = NULL;
|
||||||
thread->prev = NULL;
|
thread->prev = NULL;
|
||||||
thread->priority = THREAD_PRIORITY_NORMAL;
|
thread->priority = THREAD_PRIORITY_NORMAL;
|
||||||
thread->affinity = 1;
|
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;
|
first_thread = thread;
|
||||||
add_process_thread( process, thread );
|
add_process_thread( process, thread );
|
||||||
|
|
||||||
*thread_handle = *process_handle = -1;
|
if ((*handle = alloc_handle( current->process, thread,
|
||||||
if (current)
|
THREAD_ALL_ACCESS, inherit )) == -1) goto error;
|
||||||
|
if (add_client( fd, thread ) == -1)
|
||||||
{
|
{
|
||||||
if ((*thread_handle = alloc_handle( current->process, thread,
|
SET_ERROR( ERROR_TOO_MANY_OPEN_FILES );
|
||||||
THREAD_ALL_ACCESS, thread_inherit )) == -1)
|
goto error;
|
||||||
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;
|
return thread;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (current)
|
if (current) close_handle( current->process, *handle );
|
||||||
{
|
|
||||||
close_handle( current->process, *thread_handle );
|
|
||||||
close_handle( current->process, *process_handle );
|
|
||||||
}
|
|
||||||
remove_process_thread( process, thread );
|
remove_process_thread( process, thread );
|
||||||
release_object( thread );
|
release_object( thread );
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -153,7 +154,6 @@ static void destroy_thread( struct object *obj )
|
||||||
if (thread->next) thread->next->prev = thread->prev;
|
if (thread->next) thread->next->prev = thread->prev;
|
||||||
if (thread->prev) thread->prev->next = thread->next;
|
if (thread->prev) thread->prev->next = thread->next;
|
||||||
else first_thread = thread->next;
|
else first_thread = thread->next;
|
||||||
if (thread->name) free( thread->name );
|
|
||||||
if (thread->apc) free( thread->apc );
|
if (thread->apc) free( thread->apc );
|
||||||
if (debug_level) memset( thread, 0xaa, sizeof(thread) ); /* catch errors */
|
if (debug_level) memset( thread, 0xaa, sizeof(thread) ); /* catch errors */
|
||||||
free( thread );
|
free( thread );
|
||||||
|
@ -165,8 +165,8 @@ static void dump_thread( struct object *obj, int verbose )
|
||||||
struct thread *thread = (struct thread *)obj;
|
struct thread *thread = (struct thread *)obj;
|
||||||
assert( obj->ops == &thread_ops );
|
assert( obj->ops == &thread_ops );
|
||||||
|
|
||||||
fprintf( stderr, "Thread pid=%d fd=%d name='%s'\n",
|
fprintf( stderr, "Thread pid=%d fd=%d\n",
|
||||||
thread->unix_pid, thread->client_fd, thread->name );
|
thread->unix_pid, thread->client_fd );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int thread_signaled( struct object *obj, struct thread *thread )
|
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,
|
void get_thread_info( struct thread *thread,
|
||||||
struct get_thread_info_reply *reply )
|
struct get_thread_info_reply *reply )
|
||||||
{
|
{
|
||||||
reply->pid = thread;
|
reply->tid = thread;
|
||||||
reply->exit_code = thread->exit_code;
|
reply->exit_code = thread->exit_code;
|
||||||
reply->priority = thread->priority;
|
reply->priority = thread->priority;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,21 +6,36 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "server/thread.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 )
|
static int dump_new_thread_request( struct new_thread_request *req, int len )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " pid=%p,", req->pid );
|
fprintf( stderr, " pid=%p,", req->pid );
|
||||||
fprintf( stderr, " suspend=%d,", req->suspend );
|
fprintf( stderr, " suspend=%d,", req->suspend );
|
||||||
fprintf( stderr, " tinherit=%d,", req->tinherit );
|
fprintf( stderr, " inherit=%d", req->inherit );
|
||||||
fprintf( stderr, " pinherit=%d", req->pinherit );
|
|
||||||
return (int)sizeof(*req);
|
return (int)sizeof(*req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_new_thread_reply( struct new_thread_reply *req, int len )
|
static int dump_new_thread_reply( struct new_thread_reply *req, int len )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " tid=%p,", req->tid );
|
fprintf( stderr, " tid=%p,", req->tid );
|
||||||
fprintf( stderr, " thandle=%d,", req->thandle );
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
fprintf( stderr, " pid=%p,", req->pid );
|
|
||||||
fprintf( stderr, " phandle=%d", req->phandle );
|
|
||||||
return (int)sizeof(*req);
|
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);
|
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 )
|
static int dump_init_thread_request( struct init_thread_request *req, int len )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " unix_pid=%d,", req->unix_pid );
|
fprintf( stderr, " unix_pid=%d", req->unix_pid );
|
||||||
fprintf( stderr, " cmd_line=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) );
|
return (int)sizeof(*req);
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_terminate_process_request( struct terminate_process_request *req, int len )
|
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 )
|
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, " exit_code=%d,", req->exit_code );
|
||||||
fprintf( stderr, " priority=%d", req->priority );
|
fprintf( stderr, " priority=%d", req->priority );
|
||||||
return (int)sizeof(*req);
|
return (int)sizeof(*req);
|
||||||
|
@ -600,10 +629,14 @@ struct dumper
|
||||||
|
|
||||||
static const struct dumper dumpers[REQ_NB_REQUESTS] =
|
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,
|
{ (int(*)(void *,int))dump_new_thread_request,
|
||||||
(void(*)())dump_new_thread_reply },
|
(void(*)())dump_new_thread_reply },
|
||||||
{ (int(*)(void *,int))dump_set_debug_request,
|
{ (int(*)(void *,int))dump_set_debug_request,
|
||||||
(void(*)())0 },
|
(void(*)())0 },
|
||||||
|
{ (int(*)(void *,int))dump_init_process_request,
|
||||||
|
(void(*)())dump_init_process_reply },
|
||||||
{ (int(*)(void *,int))dump_init_thread_request,
|
{ (int(*)(void *,int))dump_init_thread_request,
|
||||||
(void(*)())0 },
|
(void(*)())0 },
|
||||||
{ (int(*)(void *,int))dump_terminate_process_request,
|
{ (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] =
|
static const char * const req_names[REQ_NB_REQUESTS] =
|
||||||
{
|
{
|
||||||
|
"new_process",
|
||||||
"new_thread",
|
"new_thread",
|
||||||
"set_debug",
|
"set_debug",
|
||||||
|
"init_process",
|
||||||
"init_thread",
|
"init_thread",
|
||||||
"terminate_process",
|
"terminate_process",
|
||||||
"terminate_thread",
|
"terminate_thread",
|
||||||
|
|
Loading…
Reference in New Issue