[Xcb-commit] libxcb: 2 commits - src

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jun 4 14:42:12 UTC 2021


 src/xcb.h      |    4 +++
 src/xcb_auth.c |   11 +++++++--
 src/xcb_conn.c |   68 ++++++++++++++++++++++++++++++++++++++-------------------
 src/xcb_in.c   |    4 +--
 src/xcb_out.c  |    4 +++
 src/xcb_util.c |    6 ++++-
 6 files changed, 70 insertions(+), 27 deletions(-)

New commits:
commit 21414e7c447f18224c577ed5e32bd5d6e45c44f9
Author: Peter Harris <pharris at opentext.com>
Date:   Mon Feb 1 19:45:28 2021 -0500

    Fix writev emulation on Windows
    
    There are at least two bugs in the previous implementation:
    
    - If an early iovec is partially written, there can be a gap of missing
      data (as a later iovec will be started before the early iovec is
      completed).
    - If a late iovec returns WSAEWOULDBLOCK, *vector and *count are not
      updated, leading to a re-send of the entire request.
    
    Move the *vector update into the send() loop to update piecemeal as
    individual iovecs are sent.
    
    Example program that demonstrates the issue (this program should run
    forever after these bugs have been fixed):
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "xcb.h"
    
    // Non-cryptographic random number generator from http://burtleburtle.net/bob/rand/smallprng.html
    // because Microsoft's random number generators either have a too small RAND_MAX or are too slow
    typedef struct ranctx { uint32_t a; uint32_t b; uint32_t c; uint32_t d; } ranctx;
    
    static uint32_t ranval(ranctx *x);
    static void raninit(ranctx *x, uint32_t seed);
    
    
    #define MAX_PROP_LEN (128 * 1024)
    
    int main(int argc, char *argv[]) {
        uint32_t seed = 0x12345678;
        if (argc > 1) {
            seed = strtoul(argv[1], NULL, 0);
        }
        ranctx ran;
        raninit(&ran, seed);
    
        xcb_connection_t *c = xcb_connect(NULL, NULL);
        if (!c || xcb_connection_has_error(c)) {
            printf("Cannot connect to $DISPLAY\n");
            return 1;
        }
        const xcb_setup_t *setup = xcb_get_setup(c);
        char *buf = malloc(MAX_PROP_LEN + 8); // plus a bit of slack so we can run random values off the end
        if (!buf) {
            printf("oom\n");
            return 1;
        }
        for (uint32_t i=0; i < (MAX_PROP_LEN + 3) / 4; i++) {
            ((uint32_t *)buf)[i] = ranval(&ran);
        }
    
        xcb_window_t win = xcb_generate_id(c);
        xcb_create_window(c, 0, win, xcb_setup_roots_iterator(setup).data[0].root, 0, 0, 1, 1, 0,
                XCB_WINDOW_CLASS_INPUT_ONLY, 0, 0, NULL);
        printf("Created window 0x%X\n", win);
    
        for (;;) {
            xcb_flush(c);
            xcb_generic_event_t *ev = xcb_poll_for_event(c);
            if (ev) {
                if (ev->response_type == 0) {
                    xcb_generic_error_t *err = (xcb_generic_error_t *)ev;
                    printf("Unexpected X Error %d\n", err->error_code);
                    printf("   Sequence %d\n", err->sequence);
                    printf("   Resource ID 0x%X\n", err->resource_id);
                    printf("   Opcode: %d.%d\n", err->major_code, err->minor_code);
                    return 1;
                }
                printf("Unexpected X Event %d\n", ev->response_type);
                return 1;
            }
    
            uint32_t siz = ranval(&ran) % MAX_PROP_LEN + 1;
            xcb_change_property(c, XCB_PROP_MODE_REPLACE, win, XCB_ATOM_STRING, XCB_ATOM_STRING, 8, siz, buf);
        }
    
        return 0;
    }
    
    
    #define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))
    static uint32_t ranval(ranctx *x) {
        uint32_t e = x->a - rot(x->b, 27);
        x->a = x->b ^ rot(x->c, 17);
        x->b = x->c + x->d;
        x->c = x->d + e;
        x->d = e + x->a;
        return x->d;
    }
    
    static void raninit(ranctx *x, uint32_t seed) {
        uint32_t i;
        x->a = 0xf1ea5eed, x->b = x->c = x->d = seed;
        for (i = 0; i<20; ++i) {
            (void)ranval(x);
        }
    }
    
    Signed-off-by: Peter Harris <pharris at opentext.com>

diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 158f676..1d2e62f 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -212,33 +212,47 @@ static int read_setup(xcb_connection_t *c)
 /* precondition: there must be something for us to write. */
 static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
 {
+#ifndef _WIN32
     int n;
+#endif
+
     assert(!c->out.queue_len);
 
 #ifdef _WIN32
-    int i = 0;
-    int ret = 0,err = 0;
-    struct iovec *vec;
-    n = 0;
-
     /* Could use the WSASend win32 function for scatter/gather i/o but setting up the WSABUF struct from
        an iovec would require more work and I'm not sure of the benefit....works for now */
-    vec = *vector;
-    while(i < *count)
+    while (*count)
     {
-         ret = send(c->fd,vec->iov_base,vec->iov_len,0);
-         if(ret == SOCKET_ERROR)
-         {
-             err  = WSAGetLastError();
-             if(err == WSAEWOULDBLOCK)
-             {
-                 return 1;
-             }
-         }
-         n += ret;
-         *vec++;
-         i++;
+        struct iovec *vec = *vector;
+        if (vec->iov_len)
+        {
+            int ret = send(c->fd, vec->iov_base, vec->iov_len, 0);
+            if (ret == SOCKET_ERROR)
+            {
+                int err = WSAGetLastError();
+                if (err == WSAEWOULDBLOCK)
+                {
+                    return 1;
+                }
+            }
+            if (ret <= 0)
+            {
+                _xcb_conn_shutdown(c, XCB_CONN_ERROR);
+                return 0;
+            }
+            c->out.total_written += ret;
+            vec->iov_len -= ret;
+            vec->iov_base = (char *)vec->iov_base + ret;
+        }
+        if (vec->iov_len == 0) {
+            (*vector)++;
+            (*count)--;
+        }
     }
+
+    if (!*count)
+        *vector = 0;
+
 #else
     n = *count;
     if (n > IOV_MAX)
@@ -280,8 +294,6 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
             return 1;
     }
 
-#endif /* _WIN32 */
-
     if(n <= 0)
     {
         _xcb_conn_shutdown(c, XCB_CONN_ERROR);
@@ -303,6 +315,9 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
     if(!*count)
         *vector = 0;
     assert(n == 0);
+
+#endif /* _WIN32 */
+
     return 1;
 }
 
commit 4b0d9d3868aad8d5f4266821e9eda586e6c2bfa7
Author: Peter Harris <pharris at opentext.com>
Date:   Mon Feb 1 17:43:52 2021 -0500

    Fix build on Windows
    
    Notable changes: Protect include of unistd.h (and other POSIX headers).
    Use SOCKET (which is larger than int) and closesocket (because close is
    not compatible) for sockets. Use <stdint.h>'s intptr_t instead of the
    non-portable ssize_t.
    
    Signed-off-by: Peter Harris <pharris at opentext.com>

diff --git a/src/xcb.h b/src/xcb.h
index 09e123e..3f39bb4 100644
--- a/src/xcb.h
+++ b/src/xcb.h
@@ -51,7 +51,11 @@ extern "C" {
  * @file xcb.h
  */
 
+#ifdef __GNUC__
 #define XCB_PACKED __attribute__((__packed__))
+#else
+#define XCB_PACKED
+#endif
 
 /**
  * @defgroup XCB_Core_API XCB Core API
diff --git a/src/xcb_auth.c b/src/xcb_auth.c
index 6937afb..8ebe9a4 100644
--- a/src/xcb_auth.c
+++ b/src/xcb_auth.c
@@ -31,8 +31,6 @@
 
 #include <assert.h>
 #include <X11/Xauth.h>
-#include <sys/param.h>
-#include <unistd.h>
 #include <stdlib.h>
 #include <time.h>
 
@@ -49,6 +47,8 @@
 #endif
 #include "xcb_windefs.h"
 #else
+#include <sys/param.h>
+#include <unistd.h>
 #include <arpa/inet.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -271,10 +271,17 @@ static int compute_auth(xcb_auth_info_t *info, Xauth *authptr, struct sockaddr *
    to the value returned by either getpeername() or getsockname()
    (according to POSIX, applications should not assume a particular
    length for `sockaddr_un.sun_path') */
+#ifdef _WIN32
+static struct sockaddr *get_peer_sock_name(int(_stdcall *socket_func)(SOCKET,
+    struct sockaddr *,
+    socklen_t *),
+    int fd)
+#else
 static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
                                                               struct sockaddr *,
                                                               socklen_t *),
                                            int fd)
+#endif
 {
     socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
     socklen_t actual_socknamelen = socknamelen;
diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 8dab658..158f676 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -32,7 +32,6 @@
 #include <assert.h>
 #include <string.h>
 #include <stdio.h>
-#include <unistd.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -48,7 +47,9 @@
 
 #ifdef _WIN32
 #include "xcb_windefs.h"
+#include <io.h>
 #else
+#include <unistd.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #endif /* _WIN32 */
@@ -345,7 +346,11 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
 
     c = calloc(1, sizeof(xcb_connection_t));
     if(!c) {
+#ifdef _WIN32
+        closesocket(fd);
+#else
         close(fd);
+#endif
         return _xcb_conn_ret_error(XCB_CONN_CLOSED_MEM_INSUFFICIENT) ;
     }
 
@@ -378,7 +383,11 @@ void xcb_disconnect(xcb_connection_t *c)
 
     /* disallow further sends and receives */
     shutdown(c->fd, SHUT_RDWR);
+#ifdef _WIN32
+    closesocket(c->fd);
+#else
     close(c->fd);
+#endif
 
     pthread_mutex_destroy(&c->iolock);
     _xcb_in_destroy(&c->in);
diff --git a/src/xcb_in.c b/src/xcb_in.c
index 796b4e9..7d02e9b 100644
--- a/src/xcb_in.c
+++ b/src/xcb_in.c
@@ -32,7 +32,6 @@
 #include <assert.h>
 #include <string.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <stdio.h>
 #include <errno.h>
 
@@ -40,6 +39,7 @@
 #include <poll.h>
 #endif
 #ifndef _WIN32
+#include <unistd.h>
 #include <sys/select.h>
 #include <sys/socket.h>
 #endif
@@ -365,7 +365,7 @@ static void free_reply_list(struct reply_list *head)
     }
 }
 
-static int read_block(const int fd, void *buf, const ssize_t len)
+static int read_block(const int fd, void *buf, const intptr_t len)
 {
     int done = 0;
     while(done < len)
diff --git a/src/xcb_out.c b/src/xcb_out.c
index c9593e5..df94867 100644
--- a/src/xcb_out.c
+++ b/src/xcb_out.c
@@ -31,7 +31,11 @@
 
 #include <assert.h>
 #include <stdlib.h>
+#ifdef _WIN32
+#include <io.h>
+#else
 #include <unistd.h>
+#endif
 #include <string.h>
 
 #include "xcb.h"
diff --git a/src/xcb_util.c b/src/xcb_util.c
index a16270c..0296ce0 100644
--- a/src/xcb_util.c
+++ b/src/xcb_util.c
@@ -36,12 +36,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
-#include <unistd.h>
 #include <string.h>
 
 #ifdef _WIN32
 #include "xcb_windefs.h"
 #else
+#include <unistd.h>
 #include <arpa/inet.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -415,7 +415,11 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
             if(_xcb_do_connect(fd, (struct sockaddr*)&_s, sizeof(_s)) >= 0)
                 break;
 
+#ifdef _WIN32
+            closesocket(fd);
+#else
             close(fd);
+#endif
             fd = -1;
             ++_c;
         }


More information about the xcb-commit mailing list