Commit 8859d772 authored by Alexandre Julliard's avatar Alexandre Julliard

Create the server pipes on the client side and transfer them to the

server on thread creation. Use a single per-process socket instead of one per thread for transferring file handles between client and server.
parent afa36ce1
......@@ -208,17 +208,27 @@ HANDLE FILE_DupUnixHandle( int fd, DWORD access )
int FILE_GetUnixHandle( HANDLE handle, DWORD access )
{
int ret, fd = -1;
SERVER_START_REQ( get_handle_fd )
do
{
req->handle = handle;
req->access = access;
if (!(ret = SERVER_CALL_ERR())) fd = req->fd;
}
SERVER_END_REQ;
if (!ret)
SERVER_START_REQ( get_handle_fd )
{
req->handle = handle;
req->access = access;
if (!(ret = SERVER_CALL_ERR())) fd = req->fd;
}
SERVER_END_REQ;
if (ret) return -1;
if (fd == -1) /* it wasn't in the cache, get it from the server */
fd = wine_server_recv_fd( handle );
} while (fd == -2); /* -2 means race condition, so restart from scratch */
if (fd != -1)
{
if (fd == -1) return wine_server_recv_fd( handle, 1 );
fd = dup(fd);
if ((fd = dup(fd)) == -1)
SetLastError( ERROR_TOO_MANY_OPEN_FILES );
}
return fd;
}
......
......@@ -163,6 +163,7 @@ struct new_thread_request
REQUEST_HEADER; /* request header */
IN int suspend; /* new thread should be suspended on creation */
IN int inherit; /* inherit flag */
IN int request_fd; /* fd for request pipe */
OUT void* tid; /* thread id */
OUT handle_t handle; /* thread handle (in the current process) */
};
......@@ -214,15 +215,8 @@ struct init_thread_request
IN int unix_pid; /* Unix pid of new thread */
IN void* teb; /* TEB of new thread (in thread address space) */
IN void* entry; /* thread entry point (in thread address space) */
};
/* Retrieve the thread buffer file descriptor */
/* The reply to this request is the first thing a newly */
/* created thread gets (without having to request it) */
struct get_thread_buffer_request
{
REQUEST_HEADER; /* request header */
IN int reply_fd; /* fd for reply pipe */
IN int wait_fd; /* fd for blocking calls pipe */
OUT void* pid; /* process id of the new thread's process */
OUT void* tid; /* thread id of the new thread */
OUT int boot; /* is this the boot thread? */
......@@ -230,6 +224,16 @@ struct get_thread_buffer_request
};
/* Set the shared buffer for a thread */
struct set_thread_buffer_request
{
REQUEST_HEADER;
IN int fd; /* fd to mmap as shared buffer */
OUT unsigned int offset; /* offset of buffer in file */
OUT unsigned int size; /* size of buffer */
};
/* Terminate a process */
struct terminate_process_request
{
......@@ -1379,7 +1383,7 @@ enum request
REQ_init_process,
REQ_init_process_done,
REQ_init_thread,
REQ_get_thread_buffer,
REQ_set_thread_buffer,
REQ_terminate_process,
REQ_terminate_thread,
REQ_get_process_info,
......@@ -1495,7 +1499,7 @@ union generic_request
struct init_process_request init_process;
struct init_process_done_request init_process_done;
struct init_thread_request init_thread;
struct get_thread_buffer_request get_thread_buffer;
struct set_thread_buffer_request set_thread_buffer;
struct terminate_process_request terminate_process;
struct terminate_thread_request terminate_thread;
struct get_process_info_request get_process_info;
......@@ -1599,7 +1603,7 @@ union generic_request
struct async_result_request async_result;
};
#define SERVER_PROTOCOL_VERSION 40
#define SERVER_PROTOCOL_VERSION 41
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
......@@ -1622,7 +1626,7 @@ extern void server_protocol_error( const char *err, ... ) WINE_NORETURN;
extern void server_protocol_perror( const char *err ) WINE_NORETURN;
extern void wine_server_alloc_req( union generic_request *req, size_t size );
extern void wine_server_send_fd( int fd );
extern int wine_server_recv_fd( int handle, int cache );
extern int wine_server_recv_fd( handle_t handle );
extern const char *get_config_dir(void);
/* do a server call and set the last error code */
......@@ -1694,10 +1698,10 @@ struct __server_exception_frame
#define SERVER_CALL_ERR() (__server_call_err( &__req, sizeof(*req) ))
extern int CLIENT_InitServer(void);
extern int CLIENT_BootDone( int debug_level );
extern void CLIENT_InitServer(void);
extern void CLIENT_InitThread(void);
extern void CLIENT_BootDone( int debug_level );
extern int CLIENT_IsBootThread(void);
extern int CLIENT_InitThread(void);
#endif /* __WINE_SERVER__ */
#endif /* __WINE_SERVER_H */
......@@ -92,19 +92,18 @@ typedef struct _TEB
/* The following are Wine-specific fields (NT: GDI stuff) */
DWORD cleanup; /* --3 1fc Cleanup service handle */
int socket; /* --3 200 Socket for server communication */
void *buffer; /* --3 204 Buffer shared with server */
unsigned int buffer_pos; /* --3 208 Buffer current position */
unsigned int buffer_size; /* --3 20c Buffer size */
int request_fd; /* --3 210 fd for sending server requests */
int reply_fd; /* --3 214 fd for receiving server replies */
int wait_fd; /* --3 218 fd for sleeping server requests */
void *debug_info; /* --3 21c Info for debugstr functions */
void *pthread_data; /* --3 220 Data for pthread emulation */
void *buffer; /* --3 200 Buffer shared with server */
unsigned int buffer_pos; /* --3 204 Buffer current position */
unsigned int buffer_size; /* --3 208 Buffer size */
int request_fd; /* --3 20c fd for sending server requests */
int reply_fd; /* --3 210 fd for receiving server replies */
int wait_fd; /* --3 214 fd for sleeping server requests */
void *debug_info; /* --3 218 Info for debugstr functions */
void *pthread_data; /* --3 21c Data for pthread emulation */
/* here is plenty space for wine specific fields (don't forget to change pad6!!) */
/* the following are nt specific fields */
DWORD pad6[629]; /* --n 224 */
DWORD pad6[630]; /* --n 220 */
UNICODE_STRING StaticUnicodeString; /* -2- bf8 used by advapi32 */
USHORT StaticUnicodeBuffer[261]; /* -2- c00 used by advapi32 */
DWORD pad7; /* --n e0c */
......
......@@ -269,8 +269,7 @@ static BOOL process_init( char *argv[] )
current_process.priority = 8; /* Normal */
/* Setup the server connection */
NtCurrentTeb()->socket = CLIENT_InitServer();
if (CLIENT_InitThread()) return FALSE;
CLIENT_InitServer();
/* Retrieve startup info from the server */
SERVER_START_VAR_REQ( init_process, sizeof(main_exe_name)-1 )
......
......@@ -95,7 +95,7 @@ int SYSDEPS_SpawnThread( TEB *teb )
const int flags = CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD;
if (clone( (int (*)(void *))SYSDEPS_StartThread, teb->stack_top, flags, teb ) < 0)
return -1;
if (!(flags & CLONE_FILES)) close( teb->socket ); /* close the child socket in the parent */
if (!(flags & CLONE_FILES)) close( teb->request_fd ); /* close the child socket in the parent */
return 0;
#endif
......@@ -118,7 +118,7 @@ int SYSDEPS_SpawnThread( TEB *teb )
"addl $8,%%esp" :
: "r" (sp), "g" (SYS_rfork), "g" (flags)
: "eax", "edx");
if (flags & RFFDG) close( teb->socket ); /* close the child socket in the parent */
if (flags & RFFDG) close( teb->request_fd ); /* close the child socket in the parent */
return 0;
#endif
......@@ -146,9 +146,9 @@ int SYSDEPS_SpawnThread( TEB *teb )
*/
void SYSDEPS_ExitThread( int status )
{
int socket = NtCurrentTeb()->socket;
NtCurrentTeb()->socket = -1;
close( socket );
int fd = NtCurrentTeb()->request_fd;
NtCurrentTeb()->request_fd = -1;
close( fd );
#ifdef HAVE__LWP_CREATE
_lwp_exit();
#endif
......
......@@ -89,7 +89,6 @@ static BOOL THREAD_InitTEB( TEB *teb )
teb->tibflags = TEBF_WIN32;
teb->tls_ptr = teb->tls_array;
teb->exit_code = STILL_ACTIVE;
teb->socket = -1;
teb->request_fd = -1;
teb->reply_fd = -1;
teb->wait_fd = -1;
......@@ -114,7 +113,6 @@ static void CALLBACK THREAD_FreeTEB( TEB *teb )
/* Free the associated memory */
if (teb->socket != -1) close( teb->socket );
close( teb->request_fd );
close( teb->reply_fd );
close( teb->wait_fd );
......@@ -285,38 +283,46 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
LPTHREAD_START_ROUTINE start, LPVOID param,
DWORD flags, LPDWORD id )
{
int socket = -1;
HANDLE handle = 0;
TEB *teb;
void *tid = 0;
int request_pipe[2];
if (pipe( request_pipe ) == -1)
{
SetLastError( ERROR_TOO_MANY_OPEN_FILES );
return 0;
}
fcntl( request_pipe[1], F_SETFD, 1 ); /* set close on exec flag */
wine_server_send_fd( request_pipe[0] );
SERVER_START_REQ( new_thread )
{
req->suspend = ((flags & CREATE_SUSPENDED) != 0);
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
req->suspend = ((flags & CREATE_SUSPENDED) != 0);
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
req->request_fd = request_pipe[0];
if (!SERVER_CALL_ERR())
{
handle = req->handle;
tid = req->tid;
socket = wine_server_recv_fd( handle, 0 );
}
close( request_pipe[0] );
}
SERVER_END_REQ;
if (!handle) return 0;
if (!(teb = THREAD_InitStack( NULL, stack )))
if (!handle || !(teb = THREAD_InitStack( NULL, stack )))
{
close( socket );
close( request_pipe[1] );
return 0;
}
teb->process = NtCurrentTeb()->process;
teb->socket = socket;
teb->tid = tid;
teb->request_fd = request_pipe[1];
teb->entry_point = start;
teb->entry_arg = param;
teb->startup = THREAD_Start;
teb->htask16 = GetCurrentTask();
fcntl( socket, F_SETFD, 1 ); /* set close on exec flag */
if (id) *id = (DWORD)tid;
if (SYSDEPS_SpawnThread( teb ) == -1)
......
......@@ -487,7 +487,7 @@ DECL_HANDLER(get_handle_fd)
else if (!get_error())
{
if ((fd = obj->ops->get_fd( obj )) != -1)
send_client_fd( current, fd, req->handle );
send_client_fd( current->process, fd, req->handle );
}
release_object( obj );
}
......
......@@ -147,6 +147,7 @@ struct thread *create_process( int fd )
{
struct process *process;
struct thread *thread = NULL;
int request_pipe[2];
if (!(process = alloc_object( &process_ops, fd ))) return NULL;
process->next = NULL;
......@@ -180,7 +181,14 @@ struct thread *create_process( int fd )
if (!(process->init_event = create_event( NULL, 0, 1, 0 ))) goto error;
/* create the main thread */
if (!(thread = create_thread( dup(fd), process ))) goto error;
if (pipe( request_pipe ) == -1)
{
file_set_error();
goto error;
}
send_client_fd( process, request_pipe[1], 0 );
close( request_pipe[1] );
if (!(thread = create_thread( request_pipe[0], process ))) goto error;
set_select_events( &process->obj, POLLIN ); /* start listening to events */
release_object( process );
......
......@@ -71,32 +71,6 @@ static const struct object_ops master_socket_ops =
};
struct request_socket
{
struct object obj; /* object header */
struct thread *thread; /* owning thread */
};
static void request_socket_dump( struct object *obj, int verbose );
static void request_socket_poll_event( struct object *obj, int event );
static const struct object_ops request_socket_ops =
{
sizeof(struct request_socket), /* size */
request_socket_dump, /* dump */
no_add_queue, /* add_queue */
NULL, /* remove_queue */
NULL, /* signaled */
NULL, /* satisfied */
NULL, /* get_poll_events */
request_socket_poll_event, /* poll_event */
no_get_fd, /* get_fd */
no_flush, /* flush */
no_get_file_info, /* get_file_info */
no_destroy /* destroy */
};
struct thread *current = NULL; /* thread handling the current request */
unsigned int global_error = 0; /* global error code for when no thread is current */
......@@ -199,6 +173,25 @@ static inline void call_req_handler( struct thread *thread, union generic_reques
fatal_protocol_error( current, "bad request %d\n", req );
}
/* read a request from a thread */
void read_request( struct thread *thread )
{
union generic_request req;
int ret;
if ((ret = read( thread->obj.fd, &req, sizeof(req) )) == sizeof(req))
{
call_req_handler( thread, &req );
return;
}
if (!ret) /* closed pipe */
kill_thread( thread, 0 );
else if (ret > 0)
fatal_protocol_error( thread, "partial read %d\n", ret );
else
fatal_protocol_perror( thread, "read" );
}
/* send a reply to a thread */
void send_reply( struct thread *thread, union generic_request *request )
{
......@@ -215,7 +208,7 @@ void send_reply( struct thread *thread, union generic_request *request )
else if (errno == EPIPE)
kill_thread( thread, 0 ); /* normal death */
else
fatal_protocol_perror( thread, "sendmsg" );
fatal_protocol_perror( thread, "reply write" );
}
}
......@@ -244,7 +237,11 @@ int receive_fd( struct process *process )
if (ret == sizeof(data))
{
struct thread *thread = get_thread_from_id( data.tid );
struct thread *thread;
if (data.tid) thread = get_thread_from_id( data.tid );
else thread = (struct thread *)grab_object( process->thread_list );
if (!thread || thread->process != process)
{
if (debug_level)
......@@ -259,19 +256,16 @@ int receive_fd( struct process *process )
(unsigned int)thread, data.fd, fd );
thread_add_inflight_fd( thread, data.fd, fd );
}
if (thread) release_object( thread );
return 0;
}
if (!ret)
{
set_select_events( &process->obj, -1 ); /* stop waiting on it */
}
else if (ret > 0)
if (ret >= 0)
{
fprintf( stderr, "Protocol error: process %p: partial recvmsg %d for fd\n", process, ret );
kill_process( process, NULL, 1 );
}
else if (ret < 0)
else
{
if (errno != EWOULDBLOCK && errno != EAGAIN)
{
......@@ -298,12 +292,12 @@ int send_thread_wakeup( struct thread *thread, int signaled )
}
/* send an fd to a client */
int send_client_fd( struct thread *thread, int fd, handle_t handle )
int send_client_fd( struct process *process, int fd, handle_t handle )
{
int ret;
if (debug_level)
fprintf( stderr, "%08x: *fd* %d -> %d\n", (unsigned int)thread, handle, fd );
fprintf( stderr, "%08x: *fd* %d -> %d\n", (unsigned int)current, handle, fd );
#ifdef HAVE_MSGHDR_ACCRIGHTS
msghdr.msg_accrightslen = sizeof(fd);
......@@ -317,16 +311,20 @@ int send_client_fd( struct thread *thread, int fd, handle_t handle )
myiovec.iov_base = (void *)&handle;
myiovec.iov_len = sizeof(handle);
ret = sendmsg( thread->obj.fd, &msghdr, 0 );
ret = sendmsg( process->obj.fd, &msghdr, 0 );
if (ret > 0) return 0;
if (errno == EPIPE)
if (ret == sizeof(handle)) return 0;
if (ret >= 0)
{
kill_thread( thread, 0 ); /* normal death */
fprintf( stderr, "Protocol error: process %p: partial sendmsg %d\n", process, ret );
kill_process( process, NULL, 1 );
}
else
{
fatal_protocol_perror( thread, "sendmsg" );
fprintf( stderr, "Protocol error: process %p: ", process );
perror( "sendmsg" );
kill_process( process, NULL, 1 );
}
return -1;
}
......@@ -373,60 +371,6 @@ static void master_socket_destroy( struct object *obj )
socket_cleanup();
}
static void request_socket_dump( struct object *obj, int verbose )
{
struct request_socket *sock = (struct request_socket *)obj;
assert( obj->ops == &request_socket_ops );
fprintf( stderr, "Request socket fd=%d thread=%p\n", sock->obj.fd, sock->thread );
}
/* handle a request socket event */
static void request_socket_poll_event( struct object *obj, int event )
{
struct request_socket *sock = (struct request_socket *)obj;
assert( obj->ops == &request_socket_ops );
if (event & (POLLERR | POLLHUP)) kill_thread( sock->thread, 0 );
else if (event & POLLIN)
{
struct thread *thread = sock->thread;
union generic_request req;
int ret;
if ((ret = read( sock->obj.fd, &req, sizeof(req) )) == sizeof(req))
{
call_req_handler( thread, &req );
return;
}
if (!ret) /* closed pipe */
kill_thread( thread, 0 );
else if (ret > 0)
fatal_protocol_error( thread, "partial read %d\n", ret );
else
fatal_protocol_perror( thread, "read" );
}
}
/* create a request socket and send the fd to the client thread */
struct object *create_request_socket( struct thread *thread )
{
struct request_socket *sock;
int fd[2];
if (pipe( fd )) return NULL;
if (!(sock = alloc_object( &request_socket_ops, fd[0] )))
{
close( fd[1] );
return NULL;
}
sock->thread = thread;
send_client_fd( thread, fd[1], 0 );
close( fd[1] );
fcntl( fd[0], F_SETFL, O_NONBLOCK );
set_select_events( &sock->obj, POLLIN );
return &sock->obj;
}
/* return the configuration directory ($WINEPREFIX or $HOME/.wine) */
const char *get_config_dir(void)
{
......
......@@ -33,12 +33,12 @@ extern void fatal_perror( const char *err, ... ) WINE_NORETURN;
extern const char *get_config_dir(void);
extern int receive_fd( struct process *process );
extern int send_thread_wakeup( struct thread *thread, int signaled );
extern int send_client_fd( struct thread *thread, int fd, handle_t handle );
extern int send_client_fd( struct process *process, int fd, handle_t handle );
extern void read_request( struct thread *thread );
extern void send_reply( struct thread *thread, union generic_request *request );
extern void open_master_socket(void);
extern void close_master_socket(void);
extern void lock_master_socket( int locked );
extern struct object *create_request_socket( struct thread *thread );
extern void trace_request( struct thread *thread, const union generic_request *request );
extern void trace_reply( struct thread *thread, const union generic_request *request );
......@@ -71,7 +71,7 @@ DECL_HANDLER(boot_done);
DECL_HANDLER(init_process);
DECL_HANDLER(init_process_done);
DECL_HANDLER(init_thread);
DECL_HANDLER(get_thread_buffer);
DECL_HANDLER(set_thread_buffer);
DECL_HANDLER(terminate_process);
DECL_HANDLER(terminate_thread);
DECL_HANDLER(get_process_info);
......@@ -186,7 +186,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_init_process,
(req_handler)req_init_process_done,
(req_handler)req_init_thread,
(req_handler)req_get_thread_buffer,
(req_handler)req_set_thread_buffer,
(req_handler)req_terminate_process,
(req_handler)req_terminate_thread,
(req_handler)req_get_process_info,
......
......@@ -17,10 +17,6 @@
#include <sys/mman.h>
#endif
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#include <sys/uio.h>
#include <unistd.h>
#include <stdarg.h>
......@@ -84,61 +80,6 @@ static const struct object_ops thread_ops =
static struct thread *first_thread;
static struct thread *booting_thread;
/* allocate the buffer for the communication with the client */
static int alloc_client_buffer( struct thread *thread )
{
union generic_request *req;
int fd = -1, fd_pipe[2], wait_pipe[2];
wait_pipe[0] = wait_pipe[1] = -1;
if (pipe( fd_pipe ) == -1)
{
file_set_error();
return 0;
}
if (pipe( wait_pipe ) == -1) goto error;
if ((fd = create_anonymous_file()) == -1) goto error;
if (ftruncate( fd, MAX_REQUEST_LENGTH ) == -1) goto error;
if ((thread->buffer = mmap( 0, MAX_REQUEST_LENGTH, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0 )) == (void*)-1) goto error;
if (!(thread->request_fd = create_request_socket( thread ))) goto error;
thread->reply_fd = fd_pipe[1];
thread->wait_fd = wait_pipe[1];
/* make the pipes non-blocking */
fcntl( fd_pipe[1], F_SETFL, O_NONBLOCK );
fcntl( wait_pipe[1], F_SETFL, O_NONBLOCK );
/* build the first request into the buffer and send it */
req = thread->buffer;
req->get_thread_buffer.pid = get_process_id( thread->process );
req->get_thread_buffer.tid = get_thread_id( thread );
req->get_thread_buffer.boot = (thread == booting_thread);
req->get_thread_buffer.version = SERVER_PROTOCOL_VERSION;
/* add it here since send_client_fd may call kill_thread */
add_process_thread( thread->process, thread );
send_client_fd( thread, fd_pipe[0], 0 );
send_client_fd( thread, wait_pipe[0], 0 );
send_client_fd( thread, fd, 0 );
send_reply( thread, req );
close( fd_pipe[0] );
close( wait_pipe[0] );
close( fd );
return 1;
error:
file_set_error();
if (fd != -1) close( fd );
close( fd_pipe[0] );
close( fd_pipe[1] );
if (wait_pipe[0] != -1) close( wait_pipe[0] );
if (wait_pipe[1] != -1) close( wait_pipe[1] );
return 0;
}
/* initialize the structure for a newly allocated thread */
inline static void init_thread_structure( struct thread *thread )
{
......@@ -170,7 +111,6 @@ inline static void init_thread_structure( struct thread *thread )
thread->affinity = 1;
thread->suspend = 0;
thread->buffer = (void *)-1;
thread->last_req = REQ_get_thread_buffer;
for (i = 0; i < MAX_INFLIGHT_FDS; i++)
thread->inflight[i].server = thread->inflight[i].client = -1;
......@@ -181,9 +121,6 @@ struct thread *create_thread( int fd, struct process *process )
{
struct thread *thread;
int flags = fcntl( fd, F_GETFL, 0 );
fcntl( fd, F_SETFL, flags | O_NONBLOCK );
if (!(thread = alloc_object( &thread_ops, fd ))) return NULL;
init_thread_structure( thread );
......@@ -200,15 +137,10 @@ struct thread *create_thread( int fd, struct process *process )
if ((thread->next = first_thread) != NULL) thread->next->prev = thread;
first_thread = thread;
#if 0
fcntl( fd, F_SETFL, O_NONBLOCK );
set_select_events( &thread->obj, POLLIN ); /* start listening to events */
#endif
if (!alloc_client_buffer( thread )) goto error;
add_process_thread( thread->process, thread );
return thread;
error:
release_object( thread );
return NULL;
}
/* handle a client event */
......@@ -218,9 +150,7 @@ static void thread_poll_event( struct object *obj, int event )
assert( obj->ops == &thread_ops );
if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
#if 0
else if (event & POLLIN) read_request( thread );
#endif
}
/* cleanup everything that is no longer needed by a dead thread */
......@@ -773,8 +703,6 @@ struct thread_snapshot *thread_snap( int *count )
DECL_HANDLER(boot_done)
{
debug_level = max( debug_level, req->debug_level );
/* Make sure last_req is initialized */
current->last_req = REQ_boot_done;
if (current == booting_thread)
{
booting_thread = (struct thread *)~0UL; /* make sure it doesn't match other threads */
......@@ -786,48 +714,97 @@ DECL_HANDLER(boot_done)
DECL_HANDLER(new_thread)
{
struct thread *thread;
int sock[2];
int request_fd = thread_get_inflight_fd( current, req->request_fd );
if (socketpair( AF_UNIX, SOCK_STREAM, 0, sock ) != -1)
if (request_fd == -1)
{
if ((thread = create_thread( sock[0], current->process )))
set_error( STATUS_INVALID_HANDLE );
return;
}
if ((thread = create_thread( request_fd, current->process )))
{
if (req->suspend) thread->suspend++;
req->tid = thread;
if ((req->handle = alloc_handle( current->process, thread,
THREAD_ALL_ACCESS, req->inherit )))
{
if (req->suspend) thread->suspend++;
req->tid = thread;
if ((req->handle = alloc_handle( current->process, thread,
THREAD_ALL_ACCESS, req->inherit )))
{
send_client_fd( current, sock[1], req->handle );
close( sock[1] );
/* thread object will be released when the thread gets killed */
return;
}
kill_thread( thread, 1 );
/* thread object will be released when the thread gets killed */
return;
}
close( sock[1] );
kill_thread( thread, 1 );
request_fd = -1;
}
else file_set_error();
}
/* retrieve the thread buffer file descriptor */
DECL_HANDLER(get_thread_buffer)
{
fatal_protocol_error( current, "get_thread_buffer: should never get called directly\n" );
}
/* initialize a new thread */
DECL_HANDLER(init_thread)
{
int reply_fd = thread_get_inflight_fd( current, req->reply_fd );
int wait_fd = thread_get_inflight_fd( current, req->wait_fd );
if (current->unix_pid)
{
fatal_protocol_error( current, "init_thread: already running\n" );
return;
goto error;
}
if (reply_fd == -1)
{
fatal_protocol_error( current, "bad reply fd\n" );
goto error;
}
if (wait_fd == -1)
{
fatal_protocol_error( current, "bad wait fd\n" );
goto error;
}
current->unix_pid = req->unix_pid;
current->teb = req->teb;
current->reply_fd = reply_fd;
current->wait_fd = wait_fd;
if (current->suspend + current->process->suspend > 0) stop_thread( current );
if (current->process->running_threads > 1)
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
req->pid = get_process_id( current->process );
req->tid = get_thread_id( current );
req->boot = (current == booting_thread);
req->version = SERVER_PROTOCOL_VERSION;
return;
error:
if (reply_fd != -1) close( reply_fd );
if (wait_fd != -1) close( wait_fd );
}
/* set the shared buffer for a thread */
DECL_HANDLER(set_thread_buffer)
{
unsigned int size = MAX_REQUEST_LENGTH;
unsigned int offset = 0;
int fd = thread_get_inflight_fd( current, req->fd );
req->size = size;
req->offset = offset;
if (fd != -1)
{
if (ftruncate( fd, size ) == -1) file_set_error();
else
{
void *buffer = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset );
if (buffer == (void *)-1) file_set_error();
else
{
if (current->buffer != (void *)-1) munmap( current->buffer, size );
current->buffer = buffer;
}
}
close( fd );
}
else set_error( STATUS_INVALID_HANDLE );
}
/* terminate a thread */
......
......@@ -75,7 +75,6 @@ struct thread
int affinity; /* affinity mask */
int suspend; /* suspend count */
void *buffer; /* buffer for communication with the client */
enum request last_req; /* last request received (for debugging) */
};
struct thread_snapshot
......
......@@ -299,7 +299,8 @@ static void dump_get_new_process_info_reply( const struct get_new_process_info_r
static void dump_new_thread_request( const struct new_thread_request *req )
{
fprintf( stderr, " suspend=%d,", req->suspend );
fprintf( stderr, " inherit=%d", req->inherit );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " request_fd=%d", req->request_fd );
}
static void dump_new_thread_reply( const struct new_thread_request *req )
......@@ -351,14 +352,12 @@ static void dump_init_thread_request( const struct init_thread_request *req )
{
fprintf( stderr, " unix_pid=%d,", req->unix_pid );
fprintf( stderr, " teb=%p,", req->teb );
fprintf( stderr, " entry=%p", req->entry );
}
static void dump_get_thread_buffer_request( const struct get_thread_buffer_request *req )
{
fprintf( stderr, " entry=%p,", req->entry );
fprintf( stderr, " reply_fd=%d,", req->reply_fd );
fprintf( stderr, " wait_fd=%d", req->wait_fd );
}
static void dump_get_thread_buffer_reply( const struct get_thread_buffer_request *req )
static void dump_init_thread_reply( const struct init_thread_request *req )
{
fprintf( stderr, " pid=%p,", req->pid );
fprintf( stderr, " tid=%p,", req->tid );
......@@ -366,6 +365,17 @@ static void dump_get_thread_buffer_reply( const struct get_thread_buffer_request
fprintf( stderr, " version=%d", req->version );
}
static void dump_set_thread_buffer_request( const struct set_thread_buffer_request *req )
{
fprintf( stderr, " fd=%d", req->fd );
}
static void dump_set_thread_buffer_reply( const struct set_thread_buffer_request *req )
{
fprintf( stderr, " offset=%08x,", req->offset );
fprintf( stderr, " size=%08x", req->size );
}
static void dump_terminate_process_request( const struct terminate_process_request *req )
{
fprintf( stderr, " handle=%d,", req->handle );
......@@ -1492,7 +1502,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_init_process_request,
(dump_func)dump_init_process_done_request,
(dump_func)dump_init_thread_request,
(dump_func)dump_get_thread_buffer_request,
(dump_func)dump_set_thread_buffer_request,
(dump_func)dump_terminate_process_request,
(dump_func)dump_terminate_thread_request,
(dump_func)dump_get_process_info_request,
......@@ -1603,8 +1613,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)0,
(dump_func)dump_init_process_reply,
(dump_func)dump_init_process_done_reply,
(dump_func)0,
(dump_func)dump_get_thread_buffer_reply,
(dump_func)dump_init_thread_reply,
(dump_func)dump_set_thread_buffer_reply,
(dump_func)dump_terminate_process_reply,
(dump_func)dump_terminate_thread_reply,
(dump_func)dump_get_process_info_reply,
......@@ -1716,7 +1726,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"init_process",
"init_process_done",
"init_thread",
"get_thread_buffer",
"set_thread_buffer",
"terminate_process",
"terminate_thread",
"get_process_info",
......@@ -1884,7 +1894,6 @@ void trace_request( struct thread *thread, const union generic_request *request
{
enum request req = request->header.req;
cur_pos = 0;
current->last_req = req;
if (req < REQ_NB_REQUESTS)
{
fprintf( stderr, "%08x: %s(", (unsigned int)thread, req_names[req] );
......@@ -1897,14 +1906,20 @@ void trace_request( struct thread *thread, const union generic_request *request
void trace_reply( struct thread *thread, const union generic_request *request )
{
fprintf( stderr, "%08x: %s() = %s",
(unsigned int)thread, req_names[thread->last_req], get_status_name(thread->error) );
if (reply_dumpers[thread->last_req])
enum request req = request->header.req;
if (req < REQ_NB_REQUESTS)
{
fprintf( stderr, " {" );
cur_pos = 0;
reply_dumpers[thread->last_req]( request );
fprintf( stderr, " }" );
fprintf( stderr, "%08x: %s() = %s",
(unsigned int)thread, req_names[req], get_status_name(thread->error) );
if (reply_dumpers[req])
{
fprintf( stderr, " {" );
cur_pos = 0;
reply_dumpers[req]( request );
fprintf( stderr, " }" );
}
fputc( '\n', stderr );
}
fputc( '\n', stderr );
else fprintf( stderr, "%08x: %d() = %s\n",
(unsigned int)thread, req, get_status_name(thread->error) );
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment