[Xcb] [PATCH xcb/libxcb] Fatal error message when we close libX11 window application

Arvind Umrao arvind.umrao at oracle.com
Fri Oct 21 03:35:18 PDT 2011


Fixes:https://bugs.freedesktop.org/show_bug.cgi?id=41443

When we close any libX11 window application, we get fatal error.
XIO:  fatal IO error 11 (Resource temporarily unavailable).
Fatal error messages are strange and confusing to developers.
Error is simply because we quit the application, without exiting
while loop of XNextEvent. XCB should give same error messages as
legacy libX11 were. In order to fix this issue, I have set right error
number at xcb_connection_t::has_error.This xcb_connection_t::has_error
will be passed to default io handler of libX11, This value could then
be used to display corrrect error messages in default IO error
handler of libX11.

Signed-off-by: Arvind Umrao <arvind.umrao at oracle.com>
---
 src/xcb.h      |    7 ++++---
 src/xcb_conn.c |    8 ++++----
 src/xcb_in.c   |   14 +++++++-------
 src/xcb_out.c  |    5 +++--
 src/xcbint.h   |   13 ++++++++++++-
 5 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/src/xcb.h b/src/xcb.h
index 3ee7965..46b5c9c 100644
--- a/src/xcb.h
+++ b/src/xcb.h
@@ -396,15 +396,16 @@ int xcb_get_file_descriptor(xcb_connection_t *c);
 /**
  * @brief Test whether the connection has shut down due to a fatal error.
  * @param c: The connection.
- * @return 1 if the connection is in an error state; 0 otherwise.
+ * @return > 0 if the connection is in an error state; 0 otherwise.
  *
  * Some errors that occur in the context of an xcb_connection_t
  * are unrecoverable. When such an error occurs, the
  * connection is shut down and further operations on the
  * xcb_connection_t have no effect.
  *
- * @todo Other functions should document the conditions in
- * which they shut down the connection.
+ * @return 1, connection error because of socket errors, pipe errors or other stream errors.
+ * @return 2, connection closed when extension not supported.
+ * @return 3, connection closed when memory not available. Error from malloc() upon failure.
  */
 int xcb_connection_has_error(xcb_connection_t *c);
 
diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 3ab5385..d0467c2 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -209,7 +209,7 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
 
     if(n <= 0)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, CONN_ERROR);
         return 0;
     }
 
@@ -317,9 +317,9 @@ void xcb_disconnect(xcb_connection_t *c)
 
 /* Private interface */
 
-void _xcb_conn_shutdown(xcb_connection_t *c)
+void _xcb_conn_shutdown(xcb_connection_t *c, enum xcb_conn_error_type err)
 {
-    c->has_error = 1;
+    c->has_error = err;
 }
 
 int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count)
@@ -380,7 +380,7 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
     } while (ret == -1 && errno == EINTR);
     if(ret < 0)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, CONN_ERROR);
         ret = 0;
     }
     pthread_mutex_lock(&c->iolock);
diff --git a/src/xcb_in.c b/src/xcb_in.c
index e075a40..7bb4d15 100644
--- a/src/xcb_in.c
+++ b/src/xcb_in.c
@@ -174,7 +174,7 @@ static int read_packet(xcb_connection_t *c)
             (genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t)));
     if(!buf)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, CONN_CLOSED_MEMORY_INSUFFICIENT);
         return 0;
     }
 
@@ -210,7 +210,7 @@ static int read_packet(xcb_connection_t *c)
         struct reply_list *cur = malloc(sizeof(struct reply_list));
         if(!cur)
         {
-            _xcb_conn_shutdown(c);
+            _xcb_conn_shutdown(c, CONN_CLOSED_MEMORY_INSUFFICIENT);
             free(buf);
             return 0;
         }
@@ -227,7 +227,7 @@ static int read_packet(xcb_connection_t *c)
     event = malloc(sizeof(struct event_list));
     if(!event)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, CONN_CLOSED_MEMORY_INSUFFICIENT);
         free(buf);
         return 0;
     }
@@ -433,7 +433,7 @@ static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_nex
     pend = malloc(sizeof(*pend));
     if(!pend)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, CONN_CLOSED_MEMORY_INSUFFICIENT);
         return;
     }
 
@@ -633,7 +633,7 @@ int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds
     assert(workaround != WORKAROUND_NONE || flags != 0);
     if(!pend)
     {
-        _xcb_conn_shutdown(c);
+        _xcb_conn_shutdown(c, CONN_CLOSED_MEMORY_INSUFFICIENT);
         return 0;
     }
     pend->first_request = pend->last_request = request;
@@ -672,7 +672,7 @@ int _xcb_in_read(xcb_connection_t *c)
     if((n > 0) || (n < 0 && WSAGetLastError() == WSAEWOULDBLOCK))
 #endif /* !_WIN32 */
         return 1;
-    _xcb_conn_shutdown(c);
+    _xcb_conn_shutdown(c, CONN_ERROR);
     return 0;
 }
 
@@ -691,7 +691,7 @@ int _xcb_in_read_block(xcb_connection_t *c, void *buf, int len)
         int ret = read_block(c->fd, (char *) buf + done, len - done);
         if(ret <= 0)
         {
-            _xcb_conn_shutdown(c);
+            _xcb_conn_shutdown(c, CONN_ERROR);
             return ret;
         }
     }
diff --git a/src/xcb_out.c b/src/xcb_out.c
index 5eb1e42..3d5aaaa 100644
--- a/src/xcb_out.c
+++ b/src/xcb_out.c
@@ -29,6 +29,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
 
 #include "xcb.h"
 #include "xcbext.h"
@@ -173,7 +174,7 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
             const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext);
             if(!(extension && extension->present))
             {
-                _xcb_conn_shutdown(c);
+                _xcb_conn_shutdown(c, CONN_CLOSED_EXT_NOTSUPPORTED);
                 return 0;
             }
             ((uint8_t *) vector[0].iov_base)[0] = extension->major_opcode;
@@ -203,7 +204,7 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
         }
         else if(longlen > xcb_get_maximum_request_length(c))
         {
-            _xcb_conn_shutdown(c);
+            _xcb_conn_shutdown(c, CONN_ERROR);
             return 0; /* server can't take this; maybe need BIGREQUESTS? */
         }
 
diff --git a/src/xcbint.h b/src/xcbint.h
index 096576c..1f37396 100644
--- a/src/xcbint.h
+++ b/src/xcbint.h
@@ -51,6 +51,17 @@ enum lazy_reply_tag
     LAZY_FORCED
 };
 
+enum xcb_conn_error_type
+{
+    /* xcb connection shutdown because of connection errors for eg socket errors, pipe errors and other stream errors. */
+    CONN_ERROR = 1,
+    /* xcb connection shutdown because of extension not sppported */
+    CONN_CLOSED_EXT_NOTSUPPORTED,
+    /* The Unix98 standard malloc(), calloc(), and realloc() error upon failure, for eg ENOMEM */
+    CONN_CLOSED_MEMORY_INSUFFICIENT
+    /* TBD: Add more error state here.*/
+};
+
 #define XCB_PAD(i) (-(i) & 3)
 
 #define XCB_SEQUENCE_COMPARE(a,op,b)	((int64_t) ((a) - (b)) op 0)
@@ -193,7 +204,7 @@ struct xcb_connection_t {
     _xcb_xid xid;
 };
 
-void _xcb_conn_shutdown(xcb_connection_t *c);
+void _xcb_conn_shutdown(xcb_connection_t *c, enum xcb_conn_error_type err);
 int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count);
 
 
-- 
1.7.3.2



More information about the Xcb mailing list