Alexandre Julliard : server: Make the fd passing code slightly more portable.

Alexandre Julliard julliard at winehq.org
Tue Oct 5 14:41:49 CDT 2010


Module: wine
Branch: stable
Commit: bd0a91a48f81528495d3e8bf2370feafc3d13d7d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=bd0a91a48f81528495d3e8bf2370feafc3d13d7d

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Sep 30 11:53:07 2010 +0200

server: Make the fd passing code slightly more portable.
(cherry picked from commit 179715251dbb399768ae0ef423ae094c4438face)

---

 dlls/ntdll/server.c |   76 +++++++++++++++++--------------------------
 server/request.c    |   88 ++++++++++++++++++++++++++++-----------------------
 2 files changed, 78 insertions(+), 86 deletions(-)

diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index 8564c0a..bc150ea 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -97,20 +97,6 @@ static const enum cpu_type client_cpu = CPU_SPARC;
 unsigned int server_cpus = 0;
 int is_wow64 = FALSE;
 
-#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-/* data structure used to pass an fd with sendmsg/recvmsg */
-struct cmsg_fd
-{
-    struct
-    {
-        size_t len;   /* size of structure */
-        int    level; /* SOL_SOCKET */
-        int    type;  /* SCM_RIGHTS */
-    } header;
-    int fd;          /* fd to pass */
-};
-#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-
 timeout_t server_start_time = 0;  /* time of server startup */
 
 sigset_t server_block_set;  /* signals to block during server calls */
@@ -332,35 +318,36 @@ void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sig
  */
 void CDECL wine_server_send_fd( int fd )
 {
-#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-    struct cmsg_fd cmsg;
-#endif
     struct send_fd data;
     struct msghdr msghdr;
     struct iovec vec;
     int ret;
 
-    vec.iov_base = (void *)&data;
-    vec.iov_len  = sizeof(data);
-
-    msghdr.msg_name    = NULL;
-    msghdr.msg_namelen = 0;
-    msghdr.msg_iov     = &vec;
-    msghdr.msg_iovlen  = 1;
-
 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     msghdr.msg_accrights    = (void *)&fd;
     msghdr.msg_accrightslen = sizeof(fd);
 #else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-    cmsg.header.len   = sizeof(cmsg.header) + sizeof(fd);
-    cmsg.header.level = SOL_SOCKET;
-    cmsg.header.type  = SCM_RIGHTS;
-    cmsg.fd           = fd;
-    msghdr.msg_control    = &cmsg;
-    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
+    char cmsg_buffer[256];
+    struct cmsghdr *cmsg;
+    msghdr.msg_control    = cmsg_buffer;
+    msghdr.msg_controllen = sizeof(cmsg_buffer);
     msghdr.msg_flags      = 0;
+    cmsg = CMSG_FIRSTHDR( &msghdr );
+    cmsg->cmsg_len   = CMSG_LEN( sizeof(fd) );
+    cmsg->cmsg_level = SOL_SOCKET;
+    cmsg->cmsg_type  = SCM_RIGHTS;
+    *(int *)CMSG_DATA(cmsg) = fd;
+    msghdr.msg_controllen = cmsg->cmsg_len;
 #endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
+    msghdr.msg_name    = NULL;
+    msghdr.msg_namelen = 0;
+    msghdr.msg_iov     = &vec;
+    msghdr.msg_iovlen  = 1;
+
+    vec.iov_base = (void *)&data;
+    vec.iov_len  = sizeof(data);
+
     data.tid = GetCurrentThreadId();
     data.fd  = fd;
 
@@ -383,24 +370,16 @@ void CDECL wine_server_send_fd( int fd )
 static int receive_fd( obj_handle_t *handle )
 {
     struct iovec vec;
-    int ret, fd;
-
-#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     struct msghdr msghdr;
+    int ret, fd = -1;
 
-    fd = -1;
+#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     msghdr.msg_accrights    = (void *)&fd;
     msghdr.msg_accrightslen = sizeof(fd);
 #else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-    struct msghdr msghdr;
-    struct cmsg_fd cmsg;
-
-    cmsg.header.len   = sizeof(cmsg.header) + sizeof(fd);
-    cmsg.header.level = SOL_SOCKET;
-    cmsg.header.type  = SCM_RIGHTS;
-    cmsg.fd           = -1;
-    msghdr.msg_control    = &cmsg;
-    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
+    char cmsg_buffer[256];
+    msghdr.msg_control    = cmsg_buffer;
+    msghdr.msg_controllen = sizeof(cmsg_buffer);
     msghdr.msg_flags      = 0;
 #endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
@@ -416,8 +395,13 @@ static int receive_fd( obj_handle_t *handle )
         if ((ret = recvmsg( fd_socket, &msghdr, MSG_CMSG_CLOEXEC )) > 0)
         {
 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-            fd = cmsg.fd;
-#endif
+            struct cmsghdr *cmsg;
+            for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg ))
+            {
+                if (cmsg->cmsg_level != SOL_SOCKET) continue;
+                if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg);
+            }
+#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
             if (fd != -1) fcntl( fd, F_SETFD, FD_CLOEXEC ); /* in case MSG_CMSG_CLOEXEC is not supported */
             return fd;
         }
diff --git a/server/request.c b/server/request.c
index d2aebb3..cea23ef 100644
--- a/server/request.c
+++ b/server/request.c
@@ -126,23 +126,6 @@ int config_dir_fd = -1;    /* file descriptor for the config dir */
 static struct master_socket *master_socket;  /* the master socket object */
 static struct timeout_user *master_timeout;
 
-/* socket communication static structures */
-static struct iovec myiovec;
-static struct msghdr msghdr;
-#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-struct cmsg_fd
-{
-    struct
-    {
-        size_t len;   /* size of structure */
-        int    level; /* SOL_SOCKET */
-        int    type;  /* SCM_RIGHTS */
-    } header;
-    int fd;           /* fd to pass */
-};
-static struct cmsg_fd cmsg = { { sizeof(cmsg.header) + sizeof(cmsg.fd), SOL_SOCKET, SCM_RIGHTS }, -1 };
-#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-
 /* complain about a protocol error and terminate the client connection */
 void fatal_protocol_error( struct thread *thread, const char *err, ... )
 {
@@ -359,25 +342,41 @@ error:
 /* receive a file descriptor on the process socket */
 int receive_fd( struct process *process )
 {
+    struct iovec vec;
     struct send_fd data;
-    int fd, ret;
+    struct msghdr msghdr;
+    int fd = -1, ret;
 
 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     msghdr.msg_accrightslen = sizeof(int);
     msghdr.msg_accrights = (void *)&fd;
 #else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-    msghdr.msg_control    = &cmsg;
-    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
-    cmsg.fd = -1;
+    char cmsg_buffer[256];
+    msghdr.msg_control    = cmsg_buffer;
+    msghdr.msg_controllen = sizeof(cmsg_buffer);
+    msghdr.msg_flags      = 0;
 #endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
-    myiovec.iov_base = (void *)&data;
-    myiovec.iov_len  = sizeof(data);
+    msghdr.msg_name    = NULL;
+    msghdr.msg_namelen = 0;
+    msghdr.msg_iov     = &vec;
+    msghdr.msg_iovlen  = 1;
+    vec.iov_base = (void *)&data;
+    vec.iov_len  = sizeof(data);
 
     ret = recvmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 );
+
 #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
-    fd = cmsg.fd;
-#endif
+    if (ret > 0)
+    {
+        struct cmsghdr *cmsg;
+        for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg ))
+        {
+            if (cmsg->cmsg_level != SOL_SOCKET) continue;
+            if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg);
+        }
+    }
+#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
     if (ret == sizeof(data))
     {
@@ -412,6 +411,7 @@ int receive_fd( struct process *process )
     {
         fprintf( stderr, "Protocol error: process %04x: partial recvmsg %d for fd\n",
                  process->id, ret );
+        if (fd != -1) close( fd );
         kill_process( process, 1 );
     }
     else
@@ -429,23 +429,37 @@ int receive_fd( struct process *process )
 /* send an fd to a client */
 int send_client_fd( struct process *process, int fd, obj_handle_t handle )
 {
+    struct iovec vec;
+    struct msghdr msghdr;
     int ret;
 
-    if (debug_level)
-        fprintf( stderr, "%04x: *fd* %04x -> %d\n",
-                 current ? current->id : process->id, handle, fd );
-
 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
     msghdr.msg_accrightslen = sizeof(fd);
     msghdr.msg_accrights = (void *)&fd;
 #else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
-    msghdr.msg_control    = &cmsg;
-    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
-    cmsg.fd = fd;
+    char cmsg_buffer[256];
+    struct cmsghdr *cmsg;
+    msghdr.msg_control    = cmsg_buffer;
+    msghdr.msg_controllen = sizeof(cmsg_buffer);
+    msghdr.msg_flags      = 0;
+    cmsg = CMSG_FIRSTHDR( &msghdr );
+    cmsg->cmsg_len   = CMSG_LEN( sizeof(fd) );
+    cmsg->cmsg_level = SOL_SOCKET;
+    cmsg->cmsg_type  = SCM_RIGHTS;
+    *(int *)CMSG_DATA(cmsg) = fd;
+    msghdr.msg_controllen = cmsg->cmsg_len;
 #endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
 
-    myiovec.iov_base = (void *)&handle;
-    myiovec.iov_len  = sizeof(handle);
+    msghdr.msg_name    = NULL;
+    msghdr.msg_namelen = 0;
+    msghdr.msg_iov     = &vec;
+    msghdr.msg_iovlen  = 1;
+
+    vec.iov_base = (void *)&handle;
+    vec.iov_len  = sizeof(handle);
+
+    if (debug_level)
+        fprintf( stderr, "%04x: *fd* %04x -> %d\n", current ? current->id : process->id, handle, fd );
 
     ret = sendmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 );
 
@@ -797,12 +811,6 @@ void open_master_socket(void)
         acquire_lock();
     }
 
-    /* setup msghdr structure constant fields */
-    msghdr.msg_name    = NULL;
-    msghdr.msg_namelen = 0;
-    msghdr.msg_iov     = &myiovec;
-    msghdr.msg_iovlen  = 1;
-
     /* init the process tracing mechanism */
     init_tracing_mechanism();
 }




More information about the wine-cvs mailing list