Fix _unserialize of reply headers
[free-sw/xcb/libxcb] / src / xcb_in.c
index 4191dc3..57d7e01 100644 (file)
 #include "xcbint.h"
 #if USE_POLL
 #include <poll.h>
-#elif !defined _WIN32
+#endif
+#ifndef _WIN32
 #include <sys/select.h>
+#include <sys/socket.h>
 #endif
 
 #ifdef _WIN32
 #define XCB_REPLY 1
 #define XCB_XGE_EVENT 35
 
+/* required for compiling for Win32 using MinGW */
+#ifndef MSG_WAITALL
+#define MSG_WAITALL 0
+#endif
+
 struct event_list {
     xcb_generic_event_t *event;
     struct event_list *next;
@@ -73,16 +80,6 @@ typedef struct reader_list {
     struct reader_list *next;
 } reader_list;
 
-static void wake_up_next_reader(xcb_connection_t *c)
-{
-    int pthreadret;
-    if(c->in.readers)
-        pthreadret = pthread_cond_signal(c->in.readers->data);
-    else
-        pthreadret = pthread_cond_signal(&c->in.event_cond);
-    assert(pthreadret == 0);
-}
-
 static int read_packet(xcb_connection_t *c)
 {
     xcb_generic_reply_t genrep;
@@ -158,9 +155,7 @@ static int read_packet(xcb_connection_t *c)
 
     /* XGE events may have sizes > 32 */
     if (genrep.response_type == XCB_XGE_EVENT)
-    {
-        eventlength = ((xcb_ge_event_t*)&genrep)->length * 4;
-    }
+        eventlength = genrep.length * 4;
 
     buf = malloc(length + eventlength +
             (genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t)));
@@ -271,12 +266,7 @@ static int read_block(const int fd, void *buf, const ssize_t len)
     int done = 0;
     while(done < len)
     {
-#ifndef _WIN32
-        int ret = read(fd, ((char *) buf) + done, len - done);
-#else
-        int ret = recv(fd, ((char *) buf) + done, len - done,0);
-#endif /* !_WIN32 */
-
+        int ret = recv(fd, ((char *) buf) + done, len - done,MSG_WAITALL);
         if(ret > 0)
             done += ret;
 #ifndef _WIN32
@@ -286,7 +276,6 @@ static int read_block(const int fd, void *buf, const ssize_t len)
 #endif /* !_Win32 */
         {
 #if USE_POLL
-#ifndef _WIN32
             struct pollfd pfd;
             pfd.fd = fd;
             pfd.events = POLLIN;
@@ -294,20 +283,16 @@ static int read_block(const int fd, void *buf, const ssize_t len)
             do {
                 ret = poll(&pfd, 1, -1);
             } while (ret == -1 && errno == EINTR);
-#endif /* !_WIN32 */
 #else
             fd_set fds;
             FD_ZERO(&fds);
             FD_SET(fd, &fds);
-#ifndef _WIN32
+
+           /* Initializing errno here makes sure that for Win32 this loop will execute only once */
+           errno = 0;  
            do {
                ret = select(fd + 1, &fds, 0, 0, 0);
            } while (ret == -1 && errno == EINTR);
-#else
-           /* the do while loop used for the non-windows version isn't required*/
-           /* for windows since there are no signals in Windows hence no EINTR*/           
-           ret = select(fd + 1, &fds, 0, 0, 0);
-#endif /* !_WIN32 */
 #endif /* USE_POLL */
         }
         if(ret <= 0)
@@ -425,7 +410,7 @@ void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_
         pthread_cond_destroy(&cond);
     }
 
-    wake_up_next_reader(c);
+    _xcb_in_wake_up_next_reader(c);
     pthread_mutex_unlock(&c->iolock);
     return ret;
 }
@@ -568,7 +553,7 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c)
         if(!_xcb_conn_wait(c, &c->in.event_cond, 0, 0))
             break;
 
-    wake_up_next_reader(c);
+    _xcb_in_wake_up_next_reader(c);
     pthread_mutex_unlock(&c->iolock);
     return ret;
 }
@@ -597,7 +582,7 @@ xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t co
     void *reply;
     if(c->has_error)
         return 0;
-    if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_expected)
+    if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>=,c->in.request_expected)
        && XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_completed))
     {
         free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), &ret));
@@ -652,6 +637,16 @@ void _xcb_in_destroy(_xcb_in *in)
     }
 }
 
+void _xcb_in_wake_up_next_reader(xcb_connection_t *c)
+{
+    int pthreadret;
+    if(c->in.readers)
+        pthreadret = pthread_cond_signal(c->in.readers->data);
+    else
+        pthreadret = pthread_cond_signal(&c->in.event_cond);
+    assert(pthreadret == 0);
+}
+
 int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds workaround, int flags)
 {
     pending_reply *pend = malloc(sizeof(pending_reply));
@@ -686,11 +681,7 @@ void _xcb_in_replies_done(xcb_connection_t *c)
 
 int _xcb_in_read(xcb_connection_t *c)
 {
-#ifndef _WIN32
-    int n = read(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len);
-#else
-    int n = recv(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len,0);
-#endif /* !_WIN32 */
+    int n = recv(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len,MSG_WAITALL);
     if(n > 0)
         c->in.queue_len += n;
     while(read_packet(c))