summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUli Schlachter <psychon@znc.in>2015-04-22 09:20:38 +0200
committerUli Schlachter <psychon@znc.in>2015-06-12 09:39:12 +0200
commit25f9e7e45a7652b35b71c7941beef774a39f0d86 (patch)
tree7dc0d72c89f545dbc7825a970b0f212f194a18e5
parentbbdf1d133f7bd979c6ff3bf44ec3d0c2d2b9dbfe (diff)
xcb_send_fd(): Always close fds
The API docs for xcb_send_fd() says "After this function returns, the file descriptor given is owned by xcb and will be closed eventually". Let the implementation live up to its documentation. We now also close fds if fd passing is unavailable (!HAVE_SENDMSG) and when the connection is in an error state. (This also does sneak in some preparatory functions for follow-up commits and thus does things in a more complicated way than really necessary.) Signed-off-by: Uli Schlachter <psychon@znc.in>
-rw-r--r--src/xcb_out.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/src/xcb_out.c b/src/xcb_out.c
index 8cc5be8..722463e 100644
--- a/src/xcb_out.c
+++ b/src/xcb_out.c
@@ -177,6 +177,34 @@ uint32_t xcb_get_maximum_request_length(xcb_connection_t *c)
return c->out.maximum_request_length.value;
}
+static void close_fds(int *fds, unsigned int num_fds)
+{
+ for (unsigned int index = 0; index < num_fds; index++)
+ close(fds[index]);
+}
+
+static void send_fds(xcb_connection_t *c, int *fds, unsigned int num_fds)
+{
+#if HAVE_SENDMSG
+ while (num_fds > 0) {
+ /* FIXME: This will busy-loop when XCB_MAX_PASS_FD fds are sent at once */
+ while (c->out.out_fd.nfd == XCB_MAX_PASS_FD && !c->has_error) {
+ /* XXX: if c->out.writing > 0, this releases the iolock and
+ * potentially allows other threads to interfere with their own fds.
+ */
+ _xcb_out_flush_to(c, c->out.request);
+ }
+ if (c->has_error)
+ break;
+
+ c->out.out_fd.fd[c->out.out_fd.nfd++] = fds[0];
+ fds++;
+ num_fds--;
+ }
+#endif
+ close_fds(fds, num_fds);
+}
+
uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
{
uint64_t request;
@@ -295,19 +323,15 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
void
xcb_send_fd(xcb_connection_t *c, int fd)
{
-#if HAVE_SENDMSG
- if (c->has_error)
+ int fds[1] = { fd };
+
+ if (c->has_error) {
+ close(fd);
return;
- 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_lock(&c->iolock);
+ send_fds(c, &fds[0], 1);
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)