[PATCH 3/7] Add xcb_send_fd API

Mark Kettenis mark.kettenis at xs4all.nl
Wed Nov 6 03:56:41 PST 2013


> From: Keith Packard <keithp at keithp.com>
> Date: Tue,  5 Nov 2013 16:41:23 -0800
> 
> This uses sendmsg to transmit file descriptors from the application to
> the X server

Same issue as with the libxtrans code; you're not using the CMSG_ API
correctly.  

Also perhaps instead of checking HAVE_SENDMSG you should simply check
SCM_RIGHTS.  All platforms that support the latter should have
sendmsg(2) while I'm not completely this is true the other way around.

> Signed-off-by: Keith Packard <keithp at keithp.com>
> ---
>  configure.ac    |  1 +
>  src/c_client.py |  4 ++++
>  src/xcb_auth.c  | 11 ++++++-----
>  src/xcb_conn.c  | 39 +++++++++++++++++++++++++++++++++------
>  src/xcb_ext.c   |  3 +++
>  src/xcb_in.c    |  9 +++++----
>  src/xcb_list.c  |  3 +++
>  src/xcb_out.c   | 19 +++++++++++++++++++
>  src/xcb_xid.c   |  4 ++++
>  src/xcbext.h    |  2 ++
>  src/xcbint.h    | 13 +++++++++++++
>  11 files changed, 93 insertions(+), 15 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index 835f7d5..2fb1968 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -80,6 +80,7 @@ AC_SUBST(XCBPROTO_XCBPYTHONDIR)
>  AC_HEADER_STDC
>  AC_SEARCH_LIBS(getaddrinfo, socket)
>  AC_SEARCH_LIBS(connect, socket)
> +AC_SEARCH_LIBS(sendmsg, socket, AC_DEFINE([HAVE_SENDMSG],1,[Define if your platform supports sendmsg]))
>  
>  have_win32="no"
>  lt_enable_auto_import=""
> diff --git a/src/c_client.py b/src/c_client.py
> index 942e78a..ed92185 100644
> --- a/src/c_client.py
> +++ b/src/c_client.py
> @@ -2149,6 +2149,10 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
>          # no padding necessary - _serialize() keeps track of padding automatically
>  
>      _c('    ')
> +    for field in param_fields:
> +        if field.isfd:
> +            _c('    xcb_send_fd(c, %s);', field.c_field_name)
> +    
>      _c('    xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
>      
>      # free dyn. all. data, if any
> diff --git a/src/xcb_auth.c b/src/xcb_auth.c
> index a5b730c..2f7c93e 100644
> --- a/src/xcb_auth.c
> +++ b/src/xcb_auth.c
> @@ -34,6 +34,12 @@
>  #include <sys/param.h>
>  #include <unistd.h>
>  #include <stdlib.h>
> +#ifndef _WIN32
> +#include <arpa/inet.h>
> +#include <sys/socket.h>
> +#include <netinet/in.h>
> +#include <sys/un.h>
> +#endif
>  
>  #ifdef __INTERIX
>  /* _don't_ ask. interix has INADDR_LOOPBACK in here. */
> @@ -47,11 +53,6 @@
>  #include <X11/Xwindows.h>
>  #endif
>  #include "xcb_windefs.h"
> -#else
> -#include <arpa/inet.h>
> -#include <sys/socket.h>
> -#include <netinet/in.h>
> -#include <sys/un.h>
>  #endif /* _WIN32 */
>  
>  #include "xcb.h"
> diff --git a/src/xcb_conn.c b/src/xcb_conn.c
> index 6a7a806..329b9e8 100644
> --- a/src/xcb_conn.c
> +++ b/src/xcb_conn.c
> @@ -38,6 +38,11 @@
>  #include <errno.h>
>  #include <limits.h>
>  
> +#ifndef _WIN32
> +#include <sys/socket.h>
> +#include <netinet/in.h>
> +#endif /* !_WIN32 */
> +
>  #include "xcb.h"
>  #include "xcbint.h"
>  #if USE_POLL
> @@ -48,9 +53,6 @@
>  
>  #ifdef _WIN32
>  #include "xcb_windefs.h"
> -#else
> -#include <sys/socket.h>
> -#include <netinet/in.h>
>  #endif /* _WIN32 */
>  
>  /* SHUT_RDWR is fairly recent and is not available on all platforms */
> @@ -214,9 +216,34 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
>      if (n > IOV_MAX)
>  	n = IOV_MAX;
>  
> -    n = writev(c->fd, *vector, n);
> -    if(n < 0 && errno == EAGAIN)
> -        return 1;
> +#if HAVE_SENDMSG
> +    if (c->out.out_fd.nfd) {
> +	struct msghdr msg = {
> +	    .msg_name = NULL,
> +	    .msg_namelen = 0,
> +	    .msg_iov = *vector,
> +	    .msg_iovlen = n,
> +	    .msg_control = &c->out.out_fd,
> +	    .msg_controllen = sizeof (struct cmsghdr) + c->out.out_fd.nfd * sizeof (int),
> +	};
> +        int i;
> +	c->out.out_fd.cmsghdr.cmsg_len = msg.msg_controllen;
> +	c->out.out_fd.cmsghdr.cmsg_level = SOL_SOCKET;
> +	c->out.out_fd.cmsghdr.cmsg_type = SCM_RIGHTS;
> +	n = sendmsg(c->fd, &msg, 0);
> +        if(n < 0 && errno == EAGAIN)
> +            return 1;
> +        for (i = 0; i < c->out.out_fd.nfd; i++)
> +            close(c->out.out_fd.fd[i]);
> +        c->out.out_fd.nfd = 0;
> +    } else
> +#endif
> +    {
> +	n = writev(c->fd, *vector, n);
> +        if(n < 0 && errno == EAGAIN)
> +            return 1;
> +    }
> +    
>  #endif /* _WIN32 */    
>  
>      if(n <= 0)
> diff --git a/src/xcb_ext.c b/src/xcb_ext.c
> index 831f283..1ff2b05 100644
> --- a/src/xcb_ext.c
> +++ b/src/xcb_ext.c
> @@ -31,6 +31,9 @@
>  
>  #include <stdlib.h>
>  #include <string.h>
> +#ifndef _WIN32
> +#include <sys/socket.h>
> +#endif
>  
>  #include "xcb.h"
>  #include "xcbext.h"
> diff --git a/src/xcb_in.c b/src/xcb_in.c
> index 8a7af92..ac4d284 100644
> --- a/src/xcb_in.c
> +++ b/src/xcb_in.c
> @@ -36,16 +36,17 @@
>  #include <stdio.h>
>  #include <errno.h>
>  
> +#ifndef _WIN32
> +#include <sys/select.h>
> +#include <sys/socket.h>
> +#endif
> +
>  #include "xcb.h"
>  #include "xcbext.h"
>  #include "xcbint.h"
>  #if USE_POLL
>  #include <poll.h>
>  #endif
> -#ifndef _WIN32
> -#include <sys/select.h>
> -#include <sys/socket.h>
> -#endif
>  
>  #ifdef _WIN32
>  #include "xcb_windefs.h"
> diff --git a/src/xcb_list.c b/src/xcb_list.c
> index 6f5c611..a219cdb 100644
> --- a/src/xcb_list.c
> +++ b/src/xcb_list.c
> @@ -30,6 +30,9 @@
>  #endif
>  
>  #include <stdlib.h>
> +#ifndef _WIN32
> +#include <sys/socket.h>
> +#endif
>  
>  #include "xcb.h"
>  #include "xcbint.h"
> diff --git a/src/xcb_out.c b/src/xcb_out.c
> index 429fa99..ed8458c 100644
> --- a/src/xcb_out.c
> +++ b/src/xcb_out.c
> @@ -33,6 +33,9 @@
>  #include <stdlib.h>
>  #include <unistd.h>
>  #include <string.h>
> +#ifndef _WIN32
> +#include <sys/socket.h>
> +#endif
>  
>  #include "xcb.h"
>  #include "xcbext.h"
> @@ -263,6 +266,22 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
>      return request;
>  }
>  
> +void
> +xcb_send_fd(xcb_connection_t *c, int fd)
> +{
> +#if HAVE_SENDMSG
> +    pthread_mutex_lock(&c->iolock);
> +    while (c->out.out_fd.nfd == XCB_MAX_PASS_FD) {
> +	_xcb_out_flush_to(c, c->out.request);
> +	if (c->has_error)
> +	    break;
> +    }
> +    if (!c->has_error)
> +	c->out.out_fd.fd[c->out.out_fd.nfd++] = fd;
> +    pthread_mutex_unlock(&c->iolock);
> +#endif
> +}
> +
>  int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent)
>  {
>      int ret;
> diff --git a/src/xcb_xid.c b/src/xcb_xid.c
> index 79a9a27..3c5682c 100644
> --- a/src/xcb_xid.c
> +++ b/src/xcb_xid.c
> @@ -31,6 +31,10 @@
>  
>  #include <assert.h>
>  #include <stdlib.h>
> +#ifndef _WIN32
> +#include <sys/socket.h>
> +#endif
> +
>  #include "xcb.h"
>  #include "xcbext.h"
>  #include "xcbint.h"
> diff --git a/src/xcbext.h b/src/xcbext.h
> index 4e1f2f7..44030c3 100644
> --- a/src/xcbext.h
> +++ b/src/xcbext.h
> @@ -59,6 +59,8 @@ enum xcb_send_request_flags_t {
>  
>  unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request);
>  
> +void xcb_send_fd(xcb_connection_t *c, int fd);
> +
>  /* xcb_take_socket allows external code to ask XCB for permission to
>   * take over the write side of the socket and send raw data with
>   * xcb_writev. xcb_take_socket provides the sequence number of the last
> diff --git a/src/xcbint.h b/src/xcbint.h
> index 7f9ab28..356350b 100644
> --- a/src/xcbint.h
> +++ b/src/xcbint.h
> @@ -81,6 +81,16 @@ void *_xcb_map_remove(_xcb_map *q, unsigned int key);
>  
>  typedef void (*xcb_return_socket_func_t)(void *closure);
>  
> +#if HAVE_SENDMSG
> +#define XCB_MAX_PASS_FD	16
> +
> +typedef struct _xcb_out_fd {
> +    struct cmsghdr cmsghdr;
> +    int fd[XCB_MAX_PASS_FD];
> +    int nfd;
> +} _xcb_out_fd;
> +#endif
> +
>  typedef struct _xcb_out {
>      pthread_cond_t cond;
>      int writing;
> @@ -101,6 +111,9 @@ typedef struct _xcb_out {
>          xcb_big_requests_enable_cookie_t cookie;
>          uint32_t value;
>      } maximum_request_length;
> +#if HAVE_SENDMSG
> +    _xcb_out_fd out_fd;
> +#endif
>  } _xcb_out;
>  
>  int _xcb_out_init(_xcb_out *out);
> -- 
> 1.8.4.2
> 
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
> 


More information about the xorg-devel mailing list