]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: Recover from closed socket
authorAxel Wagner <mail@merovius.de>
Sun, 26 Dec 2010 18:29:57 +0000 (19:29 +0100)
committerAxel Wagner <mail@merovius.de>
Sun, 26 Dec 2010 19:03:06 +0000 (20:03 +0100)
i3bar/CHANGELOG
i3bar/include/ipc.h
i3bar/src/ipc.c
i3bar/src/main.c

index b8030e4386fa4faa8a4529538096baa22cde1637..cbacfb999a6daf275e9f952e2f0dcee5efe8a975 100644 (file)
@@ -1,3 +1,5 @@
+- Bugfix: Recover from closed socket
+
 v0.6
 =====
 - Add manpage
index 0eba64fab69157b335655d70b906210eda150777..ee273a453de2d929905afd764f30a63b08b2b072 100644 (file)
  */
 int init_connection(const char *socket_path);
 
+/*
+ * Destroy the connection to i3.
+ *
+ */
+void destroy_connection();
+
 /*
  * Sends a Message to i3.
  * type must be a valid I3_IPC_MESSAGE_TYPE (see i3/ipc.h for further information)
index 0ddccc2545c06c5c667ed3f610908dcb66ed3386..bd7de75efd0131abc6a91be2f8ce808bea6234a2 100644 (file)
 
 #include "common.h"
 
-ev_io *i3_connection;
+ev_io      i3_connection;
+ev_timer   reconn;
+
+const char *sock_path;
 
 typedef void(*handler_t)(char*);
 
 /*
- * Get a connect to the IPC-interface of i3 and return a filedescriptor
+ * Retry to connect.
  *
  */
-int get_ipc_fd(const char *socket_path) {
-    int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
-    if (sockfd == -1) {
-        ELOG("Could not create Socket!\n");
-        exit(EXIT_FAILURE);
+void retry_connection(struct ev_loop *loop, ev_timer *w, int events) {
+    static int retries = 8;
+    if (init_connection(sock_path) == 0) {
+        if (retries == 0) {
+            ELOG("Retried 8 times - connection failed!\n");
+            exit(EXIT_FAILURE);
+        }
+        retries--;
+        return;
     }
+    retries = 8;
+    ev_timer_stop(loop, w);
+    subscribe_events();
+    reconfig_windows();
+}
 
-    struct sockaddr_un addr;
-    memset(&addr, 0, sizeof(struct sockaddr_un));
-    addr.sun_family = AF_LOCAL;
-    strcpy(addr.sun_path, socket_path);
-    if (connect(sockfd, (const struct sockaddr*) &addr, sizeof(struct sockaddr_un)) < 0) {
-        ELOG("Could not connct to i3!\n");
-        exit(EXIT_FAILURE);
-    }
-    return sockfd;
+/*
+ * Schedule a reconnect
+ *
+ */
+void reconnect() {
+    ev_timer_init(&reconn, retry_connection, 0.25, 0.25);
+    ev_timer_start(main_loop, &reconn);
 }
 
 /*
@@ -144,8 +154,12 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
             exit(EXIT_FAILURE);
         }
         if (n == 0) {
-            ELOG("Nothing to read!\n");
-            exit(EXIT_FAILURE);
+            /* EOF received. We try to recover a few times, because most likely
+             * i3 just restarted */
+            ELOG("EOF received, try to recover...\n");
+            destroy_connection();
+            reconnect();
+            return;
         }
         rec += n;
     }
@@ -167,8 +181,12 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
      * of the message */
     char *buffer = malloc(size + 1);
     if (buffer == NULL) {
-        ELOG("Could not allocate memory!\n");
-        exit(EXIT_FAILURE);
+        /* EOF received. We try to recover a few times, because most likely
+         * i3 just restarted */
+        ELOG("EOF received, try to recover...\n");
+        destroy_connection();
+        reconnect();
+        return;
     }
     rec = 0;
 
@@ -234,7 +252,7 @@ int i3_send_msg(uint32_t type, const char *payload) {
     uint32_t written = 0;
 
     while (to_write > 0) {
-        int n = write(i3_connection->fd, buffer + written, to_write);
+        int n = write(i3_connection.fd, buffer + written, to_write);
         if (n == -1) {
             ELOG("write() failed!\n");
             exit(EXIT_FAILURE);
@@ -255,15 +273,36 @@ int i3_send_msg(uint32_t type, const char *payload) {
  *
  */
 int init_connection(const char *socket_path) {
-    int sockfd = get_ipc_fd(socket_path);
+    sock_path = socket_path;
+    int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
+    if (sockfd == -1) {
+        ELOG("Could not create Socket!\n");
+        exit(EXIT_FAILURE);
+    }
 
-    i3_connection = malloc(sizeof(ev_io));
-    ev_io_init(i3_connection, &got_data, sockfd, EV_READ);
-    ev_io_start(main_loop, i3_connection);
+    struct sockaddr_un addr;
+    memset(&addr, 0, sizeof(struct sockaddr_un));
+    addr.sun_family = AF_LOCAL;
+    strcpy(addr.sun_path, sock_path);
+    if (connect(sockfd, (const struct sockaddr*) &addr, sizeof(struct sockaddr_un)) < 0) {
+        ELOG("Could not connct to i3!\n");
+        reconnect();
+        return 0;
+    }
 
+    ev_io_init(&i3_connection, &got_data, sockfd, EV_READ);
+    ev_io_start(main_loop, &i3_connection);
     return 1;
 }
 
+/*
+ * Destroy the connection to i3.
+ */
+void destroy_connection() {
+    close(i3_connection.fd);
+    ev_io_stop(main_loop, &i3_connection);
+}
+
 /*
  * Subscribe to all the i3-events, we need
  *
index ec85d32455476b67f43debaaa334e15a89a53b94..7f27bdac724fe4fcfd737640d9573c4ff8562220 100644 (file)
@@ -215,8 +215,6 @@ int main(int argc, char **argv) {
     init_outputs();
     init_connection(socket_path);
 
-    FREE(socket_path);
-
     /* We subscribe to the i3-events we need */
     subscribe_events();
 
@@ -249,6 +247,8 @@ int main(int argc, char **argv) {
 
     kill_child();
 
+    FREE(socket_path);
+
     FREE(statusline);
 
     clean_xcb();