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

Arvind Umrao arvind.umrao at oracle.com
Mon Oct 24 01:01:07 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      |   20 +++++++++++++++++---
 src/xcb_conn.c |    8 ++++----
 src/xcb_in.c   |   14 +++++++-------
 src/xcb_out.c  |    4 ++--
 src/xcbint.h   |    2 +-
 5 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/src/xcb.h b/src/xcb.h
index 3ee7965..24624bf 100644
--- a/src/xcb.h
+++ b/src/xcb.h
@@ -69,6 +69,18 @@ extern "C" {
 /** X_TCP_PORT + display number = server port for TCP transport */
 #define X_TCP_PORT 6000
 
+/** xcb connection shutdown because of connection errors for eg socket errors, pipe errors and other stream errors. */
+#define CONN_ERROR  1
+
+/**  xcb connection shutdown because of extension not sppported */
+#define CONN_CLOSED_EXT_NOTSUPPORTED 2
+
+/** malloc(), calloc() and realloc() error upon failure, for eg ENOMEM */
+#define CONN_CLOSED_MEMORY_INSUFFICIENT 3
+
+/** Connection closed, exceeding request length that server accepts.  */
+#define CONN_CLOSED_REQ_LEN_EXCEED  4
+
 #define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1))
 
 /* Opaque structures */
@@ -396,15 +408,17 @@ 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 CONN_ERROR, connection error because of socket errors, pipe errors or other stream errors.
+ * @return CONN_CLOSED_EXT_NOTSUPPORTED, connection closed when extension not supported.
+ * @return CONN_CLOSED_MEMORY_INSUFFICIENT, connection closed when memory not available.
+ * @return CONN_CLOSED_REQ_LEN_EXCEED, connection closed, exceeding request length that server accepts.
  */
 int xcb_connection_has_error(xcb_connection_t *c);
 
diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 3ab5385..e16f034 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, int 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..827bf53 100644
--- a/src/xcb_out.c
+++ b/src/xcb_out.c
@@ -173,7 +173,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 +203,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_CLOSED_REQ_LEN_EXCEED);
             return 0; /* server can't take this; maybe need BIGREQUESTS? */
         }
 
diff --git a/src/xcbint.h b/src/xcbint.h
index 096576c..048a3b1 100644
--- a/src/xcbint.h
+++ b/src/xcbint.h
@@ -193,7 +193,7 @@ struct xcb_connection_t {
     _xcb_xid xid;
 };
 
-void _xcb_conn_shutdown(xcb_connection_t *c);
+void _xcb_conn_shutdown(xcb_connection_t *c, int 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