> From: Keith Packard <[email protected]> > 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 <[email protected]> > --- > 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 > > _______________________________________________ > [email protected]: X.Org development > Archives: http://lists.x.org/archives/xorg-devel > Info: http://lists.x.org/mailman/listinfo/xorg-devel > _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
