[Xcb] [PATCH 3/4] xcb_connect*: cancel thread immediately during connect()

Rémi Denis-Courmont remi at remlab.net
Thu Jan 7 09:25:14 PST 2010


---
 src/xcb_util.c |   54 +++++++++++++++++++++---------------------------------
 1 files changed, 21 insertions(+), 33 deletions(-)

diff --git a/src/xcb_util.c b/src/xcb_util.c
index 3b6fcea..64049d1 100644
--- a/src/xcb_util.c
+++ b/src/xcb_util.c
@@ -125,6 +125,16 @@ static void cleanup_file(void *data)
     close((intptr_t)data);
 }
 
+static int _xcb_connect_safe(int fd, const struct sockaddr *dst, socklen_t len)
+{
+    int ret;
+
+    pthread_cleanup_push(cleanup_file, (void *)(intptr_t)fd);
+    ret = connect(fd, dst, len);
+    pthread_cleanup_pop(ret == -1);
+    return ret;
+}
+
 static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port);
 static int _xcb_open_unix(char *protocol, const char *file);
 #ifdef DNETCONN
@@ -189,7 +199,6 @@ static int _xcb_open_decnet(const char *host, const char *protocol, const unsign
     struct sockaddr_dn addr;
     struct accessdata_dn accessdata;
     struct nodeent *nodeaddr = getnodebyname(host);
-    int cancel;
 
     if(!nodeaddr)
         return -1;
@@ -215,17 +224,17 @@ static int _xcb_open_decnet(const char *host, const char *protocol, const unsign
         return -1;
     setsockopt(fd, DNPROTO_NSP, SO_CONACCESS, &accessdata, sizeof(accessdata));
 
-    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel);
-    if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
-        close(fd);
-        pthread_setcancelstate(cancel, NULL);
+    if(_xcb_connect_safe(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
         return -1;
-    }
-    pthread_setcancelstate(cancel, NULL);
     return fd;
 }
 #endif
 
+static void cleanup_addrinfo(void *data)
+{
+    freeaddrinfo(data);
+}
+
 static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port)
 {
     int fd = -1;
@@ -233,7 +242,6 @@ static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port)
     char service[6]; /* "65535" with the trailing '\0' */
     struct addrinfo *results, *addr;
     char *bracket;
-    int cancel;
 
     if (protocol && strcmp("tcp",protocol))
         return -1;
@@ -261,15 +269,13 @@ static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port)
 
     snprintf(service, sizeof(service), "%hu", port);
 
-    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel);
     if(getaddrinfo(host, service, &hints, &results))
     {
-        pthread_setcancelstate(cancel, NULL);
         /* FIXME: use gai_strerror, and fill in error connection */
         return -1;
     }
-    pthread_setcancelstate(cancel, NULL);
 
+    pthread_cleanup_push(cleanup_addrinfo, results);
     for(addr = results; addr; addr = addr->ai_next)
     {
         fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
@@ -278,25 +284,18 @@ static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port)
             setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
 	    setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
 
-            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel);
-            if (connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
-            {
-                pthread_setcancelstate(cancel, NULL);
+            if(_xcb_connect_safe(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
                 break;
-            }
-            close(fd);
-            pthread_setcancelstate(cancel, NULL);
             fd = -1;
         }
     }
-    freeaddrinfo(results);
+    pthread_cleanup_pop(1);
     return fd;
 }
 
 static int _xcb_open_unix(char *protocol, const char *file)
 {
     int fd;
-    int cancel;
     struct sockaddr_un addr;
 
     if (protocol && strcmp("unix",protocol))
@@ -310,13 +309,8 @@ static int _xcb_open_unix(char *protocol, const char *file)
     fd = socket(AF_UNIX, SOCK_STREAM, 0);
     if(fd == -1)
         return -1;
-    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel);
-    if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
-        close(fd);
-        pthread_setcancelstate(cancel, NULL);
+    if(_xcb_connect_safe(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
         return -1;
-    }
-    pthread_setcancelstate(cancel, NULL);
     return fd;
 }
 
@@ -324,7 +318,6 @@ static int _xcb_open_unix(char *protocol, const char *file)
 static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen)
 {
     int fd;
-    int cancel;
     struct sockaddr_un addr = {0};
     socklen_t namelen;
 
@@ -340,13 +333,8 @@ static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen)
     fd = socket(AF_UNIX, SOCK_STREAM, 0);
     if (fd == -1)
         return -1;
-    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel);
-    if (connect(fd, (struct sockaddr *) &addr, namelen) == -1) {
-        close(fd);
-        pthread_setcancelstate(cancel, NULL);
+    if (_xcb_connect_safe(fd, (struct sockaddr *) &addr, namelen) == -1)
         return -1;
-    }
-    pthread_setcancelstate(cancel, NULL);
     return fd;
 }
 #endif
-- 
1.6.6



More information about the Xcb mailing list