From 8859d772791bfefd27081bf1150d82b1f5559d18 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Thu, 1 Mar 2001 22:13:49 +0000
Subject: [PATCH] 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.

---
 files/file.c        |  28 ++++--
 include/server.h    |  36 ++++---
 include/thread.h    |  19 ++--
 scheduler/client.c  | 239 ++++++++++++++++++++++++++------------------
 scheduler/process.c |   3 +-
 scheduler/sysdeps.c |  10 +-
 scheduler/thread.c  |  28 ++++--
 server/file.c       |   2 +-
 server/process.c    |  10 +-
 server/request.c    | 134 ++++++++-----------------
 server/request.h    |   8 +-
 server/thread.c     | 171 ++++++++++++++-----------------
 server/thread.h     |   1 -
 server/trace.c      |  55 ++++++----
 14 files changed, 372 insertions(+), 372 deletions(-)

diff --git a/files/file.c b/files/file.c
index bcb62c781a4..c9dd1069d1d 100644
--- a/files/file.c
+++ b/files/file.c
@@ -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;
 }
diff --git a/include/server.h b/include/server.h
index a697d974878..6c15ba49b22 100644
--- a/include/server.h
+++ b/include/server.h
@@ -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 */
diff --git a/include/thread.h b/include/thread.h
index 7d84170ee02..85f5e170318 100644
--- a/include/thread.h
+++ b/include/thread.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 */
diff --git a/scheduler/client.c b/scheduler/client.c
index 1a6bc606db1..6ef25d876d5 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -93,7 +93,7 @@ void server_protocol_error( const char *err, ... )
     va_list args;
 
     va_start( args, err );
-    fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
+    fprintf( stderr, "wine client error:%p: ", NtCurrentTeb()->tid );
     vfprintf( stderr, err, args );
     va_end( args );
     SYSDEPS_ExitThread(1);
@@ -105,7 +105,7 @@ void server_protocol_error( const char *err, ... )
  */
 void server_protocol_perror( const char *err )
 {
-    fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
+    fprintf( stderr, "wine client error:%p: ", NtCurrentTeb()->tid );
     perror( err );
     SYSDEPS_ExitThread(1);
 }
@@ -252,49 +252,14 @@ void wine_server_send_fd( int fd )
 
 
 /***********************************************************************
- *           set_handle_fd
- *
- * Store the fd for a given handle in the server
- */
-static int set_handle_fd( int handle, int fd )
-{
-    SERVER_START_REQ( set_handle_info )
-    {
-        req->handle = handle;
-        req->flags  = 0;
-        req->mask   = 0;
-        req->fd     = fd;
-        if (!SERVER_CALL())
-        {
-            if (req->cur_fd != fd)
-            {
-                /* someone was here before us */
-                close( fd );
-                fd = req->cur_fd;
-            }
-            else fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
-        }
-        else
-        {
-            close( fd );
-            fd = -1;
-        }
-    }
-    SERVER_END_REQ;
-    return fd;
-}
-
-
-/***********************************************************************
- *           wine_server_recv_fd
+ *           receive_fd
  *
  * Receive a file descriptor passed from the server.
- * The file descriptor must be closed after use.
  */
-int wine_server_recv_fd( int handle, int cache )
+static int receive_fd( handle_t *handle )
 {
     struct iovec vec;
-    int ret, fd, server_handle;
+    int ret, fd;
 
 #ifdef HAVE_MSGHDR_ACCRIGHTS
     struct msghdr msghdr;
@@ -319,24 +284,18 @@ int wine_server_recv_fd( int handle, int cache )
     msghdr.msg_namelen = 0;
     msghdr.msg_iov     = &vec;
     msghdr.msg_iovlen  = 1;
-    vec.iov_base = (void *)&server_handle;
-    vec.iov_len  = sizeof(server_handle);
+    vec.iov_base = (void *)handle;
+    vec.iov_len  = sizeof(*handle);
 
     for (;;)
     {
-        if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) > 0)
+        if ((ret = recvmsg( fd_socket, &msghdr, 0 )) > 0)
         {
 #ifndef HAVE_MSGHDR_ACCRIGHTS
             fd = cmsg.fd;
 #endif
-            if (handle != server_handle)
-                server_protocol_error( "recv_fd: got handle %d, expected %d\n",
-                                       server_handle, handle );
-            if (cache)
-            {
-                fd = set_handle_fd( handle, fd );
-                if (fd != -1) fd = dup(fd);
-            }
+            if (fd == -1) server_protocol_error( "no fd received for handle %d\n", *handle );
+            fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
             return fd;
         }
         if (!ret) break;
@@ -349,6 +308,50 @@ int wine_server_recv_fd( int handle, int cache )
 }
 
 
+/***********************************************************************
+ *           wine_server_recv_fd
+ *
+ * Receive a file descriptor passed from the server.
+ * The file descriptor must be closed after use.
+ * Return -2 if a race condition stole our file descriptor.
+ */
+int wine_server_recv_fd( handle_t handle )
+{
+    handle_t fd_handle;
+
+    int fd = receive_fd( &fd_handle );
+
+    /* now store it in the server fd cache for this handle */
+
+    SERVER_START_REQ( set_handle_info )
+    {
+        req->handle = fd_handle;
+        req->flags  = 0;
+        req->mask   = 0;
+        req->fd     = fd;
+        if (!SERVER_CALL())
+        {
+            if (req->cur_fd != fd)
+            {
+                /* someone was here before us */
+                close( fd );
+                fd = req->cur_fd;
+            }
+        }
+        else
+        {
+            close( fd );
+            fd = -1;
+        }
+    }
+    SERVER_END_REQ;
+
+    if (handle != fd_handle) return -2;  /* not the one we expected */
+    if (fd != -1) fd = dup(fd);
+    return fd;
+}
+
+
 /***********************************************************************
  *           get_config_dir
  *
@@ -520,12 +523,13 @@ static int server_connect( const char *oldcwd, const char *serverdir )
  *
  * Start the server and create the initial socket pair.
  */
-int CLIENT_InitServer(void)
+void CLIENT_InitServer(void)
 {
-    int fd, size;
+    int size;
     char hostname[64];
     char *oldcwd, *serverdir;
     const char *configdir;
+    handle_t dummy_handle;
 
     /* retrieve the current directory */
     for (size = 512; ; size *= 2)
@@ -562,8 +566,7 @@ int CLIENT_InitServer(void)
     strcat( serverdir, hostname );
 
     /* connect to the server */
-    fd = server_connect( oldcwd, serverdir );
-    fd_socket = dup(fd);
+    fd_socket = server_connect( oldcwd, serverdir );
 
     /* switch back to the starting directory */
     if (oldcwd)
@@ -579,69 +582,107 @@ int CLIENT_InitServer(void)
     sigaddset( &block_set, SIGINT );
     sigaddset( &block_set, SIGHUP );
 
-    return fd;
+    /* receive the first thread request fd on the main socket */
+    NtCurrentTeb()->request_fd = receive_fd( &dummy_handle );
+
+    CLIENT_InitThread();
 }
 
 
 /***********************************************************************
- *           CLIENT_InitThread
- *
- * Send an init thread request. Return 0 if OK.
+ *           set_request_buffer
  */
-int CLIENT_InitThread(void)
+inline static void set_request_buffer(void)
 {
-    struct get_thread_buffer_request *req;
-    TEB *teb = NtCurrentTeb();
+    char *name;
     int fd, ret;
+    unsigned int offset, size;
 
-    /* ignore SIGPIPE so that we get a EPIPE error instead  */
-    signal( SIGPIPE, SIG_IGN );
+    /* create a temporary file */
+    do
+    {
+        if (!(name = tmpnam(NULL))) server_protocol_perror( "tmpnam" );
+        fd = open( name, O_CREAT | O_EXCL | O_RDWR, 0600 );
+    } while ((fd == -1) && (errno == EEXIST));
 
-    teb->request_fd = wine_server_recv_fd( 0, 0 );
-    if (teb->request_fd == -1) server_protocol_error( "no request fd passed on first request\n" );
-    fcntl( teb->request_fd, F_SETFD, 1 ); /* set close on exec flag */
+    if (fd == -1) server_protocol_perror( "create" );
+    unlink( name );
 
-    teb->reply_fd = wine_server_recv_fd( 0, 0 );
-    if (teb->reply_fd == -1) server_protocol_error( "no reply fd passed on first request\n" );
-    fcntl( teb->reply_fd, F_SETFD, 1 ); /* set close on exec flag */
+    wine_server_send_fd( fd );
 
-    teb->wait_fd = wine_server_recv_fd( 0, 0 );
-    if (teb->wait_fd == -1) server_protocol_error( "no wait fd passed on first request\n" );
-    fcntl( teb->wait_fd, F_SETFD, 1 ); /* set close on exec flag */
+    SERVER_START_REQ( set_thread_buffer )
+    {
+        req->fd = fd;
+        ret = SERVER_CALL();
+        offset = req->offset;
+        size = req->size;
+    }
+    SERVER_END_REQ;
+    if (ret) server_protocol_error( "set_thread_buffer failed with status %x\n", ret );
 
-    fd = wine_server_recv_fd( 0, 0 );
-    if (fd == -1) server_protocol_error( "no fd received for thread buffer\n" );
+    if ((NtCurrentTeb()->buffer = mmap( 0, size, PROT_READ | PROT_WRITE,
+                                        MAP_SHARED, fd, offset )) == (void*)-1)
+        server_protocol_perror( "mmap" );
 
-    if ((teb->buffer_size = lseek( fd, 0, SEEK_END )) == -1) server_protocol_perror( "lseek" );
-    teb->buffer = mmap( 0, teb->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
-    teb->buffer_pos = 0;
     close( fd );
-    if (teb->buffer == (void*)-1) server_protocol_perror( "mmap" );
+    NtCurrentTeb()->buffer_pos  = 0;
+    NtCurrentTeb()->buffer_size = size;
+}
 
-    req = (struct get_thread_buffer_request *)teb->buffer;
-    wait_reply( (union generic_request *)req );
 
-    teb->pid = req->pid;
-    teb->tid = req->tid;
-    if (req->version != SERVER_PROTOCOL_VERSION)
-        server_protocol_error( "version mismatch %d/%d.\n"
-                               "Your %s binary was not upgraded correctly,\n"
-                               "or you have an older one somewhere in your PATH.\n"
-                               "Or maybe the wrong wineserver is still running?\n",
-                               req->version, SERVER_PROTOCOL_VERSION,
-                               (req->version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
-    if (req->boot) boot_thread_id = teb->tid;
-    else if (boot_thread_id == teb->tid) boot_thread_id = 0;
+/***********************************************************************
+ *           CLIENT_InitThread
+ *
+ * Send an init thread request. Return 0 if OK.
+ */
+void CLIENT_InitThread(void)
+{
+    TEB *teb = NtCurrentTeb();
+    int version, ret;
+    int reply_pipe[2], wait_pipe[2];
+
+    /* ignore SIGPIPE so that we get a EPIPE error instead  */
+    signal( SIGPIPE, SIG_IGN );
+
+    /* create the server->client communication pipes */
+    if (pipe( reply_pipe ) == -1) server_protocol_perror( "pipe" );
+    if (pipe( wait_pipe ) == -1) server_protocol_perror( "pipe" );
+    wine_server_send_fd( reply_pipe[1] );
+    wine_server_send_fd( wait_pipe[1] );
+    teb->reply_fd = reply_pipe[0];
+    teb->wait_fd = wait_pipe[0];
+
+    /* set close on exec flag */
+    fcntl( teb->reply_fd, F_SETFD, 1 );
+    fcntl( teb->wait_fd, F_SETFD, 1 );
 
     SERVER_START_REQ( init_thread )
     {
-        req->unix_pid = getpid();
-        req->teb      = teb;
-        req->entry    = teb->entry_point;
+        req->unix_pid    = getpid();
+        req->teb         = teb;
+        req->entry       = teb->entry_point;
+        req->reply_fd    = reply_pipe[1];
+        req->wait_fd     = wait_pipe[1];
         ret = SERVER_CALL();
+        teb->pid = req->pid;
+        teb->tid = req->tid;
+        version  = req->version;
+        if (req->boot) boot_thread_id = teb->tid;
+        else if (boot_thread_id == teb->tid) boot_thread_id = 0;
+        close( reply_pipe[1] );
+        close( wait_pipe[1] );
     }
     SERVER_END_REQ;
-    return ret;
+
+    if (ret) server_protocol_error( "init_thread failed with status %x\n", ret );
+    if (version != SERVER_PROTOCOL_VERSION)
+        server_protocol_error( "version mismatch %d/%d.\n"
+                               "Your %s binary was not upgraded correctly,\n"
+                               "or you have an older one somewhere in your PATH.\n"
+                               "Or maybe the wrong wineserver is still running?\n",
+                               version, SERVER_PROTOCOL_VERSION,
+                               (version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
+    set_request_buffer();
 }
 
 
@@ -650,16 +691,14 @@ int CLIENT_InitThread(void)
  *
  * Signal that we have finished booting, and set debug level.
  */
-int CLIENT_BootDone( int debug_level )
+void CLIENT_BootDone( int debug_level )
 {
-    int ret;
     SERVER_START_REQ( boot_done )
     {
         req->debug_level = debug_level;
-        ret = SERVER_CALL();
+        SERVER_CALL();
     }
     SERVER_END_REQ;
-    return ret;
 }
 
 
diff --git a/scheduler/process.c b/scheduler/process.c
index 482cedb0d6d..ac85e655b59 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -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 )
diff --git a/scheduler/sysdeps.c b/scheduler/sysdeps.c
index 1a1a1042c6c..86ac9b95336 100644
--- a/scheduler/sysdeps.c
+++ b/scheduler/sysdeps.c
@@ -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
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 77daaacf8ed..738d4c8f378 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -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)
diff --git a/server/file.c b/server/file.c
index 0ce961aa720..75b1dd89eab 100644
--- a/server/file.c
+++ b/server/file.c
@@ -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 );
     }
diff --git a/server/process.c b/server/process.c
index 9f4bdc4a6ec..39f40e6f301 100644
--- a/server/process.c
+++ b/server/process.c
@@ -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 );
diff --git a/server/request.c b/server/request.c
index 96bb7111471..4072fd1e052 100644
--- a/server/request.c
+++ b/server/request.c
@@ -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)
 {
diff --git a/server/request.h b/server/request.h
index b4275594130..1c7b4fbd02b 100644
--- a/server/request.h
+++ b/server/request.h
@@ -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,
diff --git a/server/thread.c b/server/thread.c
index 25361c4af2b..60363c7f15e 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -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 */
diff --git a/server/thread.h b/server/thread.h
index 5d25f3c9cc6..6b71bdd9238 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -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
diff --git a/server/trace.c b/server/trace.c
index 744bc846639..14fa6f28e60 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -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) );
 }
-- 
GitLab