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.

diff --git a/server/request.c b/server/request.c
index 96bb711..4072fd1 100644
--- a/server/request.c
+++ b/server/request.c
@@ -71,32 +71,6 @@
 };
 
 
-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 @@
     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 @@
         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 @@
 
     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 @@
                          (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 @@
 }
 
 /* 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 @@
     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 @@
     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)
 {