[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