Bugfix: Recover from closed socket

This commit is contained in:
Axel Wagner 2010-12-26 19:29:57 +01:00
parent 3c85c514d4
commit 3daab599ca
4 changed files with 74 additions and 27 deletions

View File

@ -1,3 +1,5 @@
- Bugfix: Recover from closed socket
v0.6 v0.6
===== =====
- Add manpage - Add manpage

View File

@ -18,6 +18,12 @@
*/ */
int init_connection(const char *socket_path); int init_connection(const char *socket_path);
/*
* Destroy the connection to i3.
*
*/
void destroy_connection();
/* /*
* Sends a Message to i3. * Sends a Message to i3.
* type must be a valid I3_IPC_MESSAGE_TYPE (see i3/ipc.h for further information) * type must be a valid I3_IPC_MESSAGE_TYPE (see i3/ipc.h for further information)

View File

@ -19,30 +19,40 @@
#include "common.h" #include "common.h"
ev_io *i3_connection; ev_io i3_connection;
ev_timer reconn;
const char *sock_path;
typedef void(*handler_t)(char*); 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) { void retry_connection(struct ev_loop *loop, ev_timer *w, int events) {
int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); static int retries = 8;
if (sockfd == -1) { if (init_connection(sock_path) == 0) {
ELOG("Could not create Socket!\n"); if (retries == 0) {
exit(EXIT_FAILURE); 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)); * Schedule a reconnect
addr.sun_family = AF_LOCAL; *
strcpy(addr.sun_path, socket_path); */
if (connect(sockfd, (const struct sockaddr*) &addr, sizeof(struct sockaddr_un)) < 0) { void reconnect() {
ELOG("Could not connct to i3!\n"); ev_timer_init(&reconn, retry_connection, 0.25, 0.25);
exit(EXIT_FAILURE); ev_timer_start(main_loop, &reconn);
}
return sockfd;
} }
/* /*
@ -144,8 +154,12 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (n == 0) { if (n == 0) {
ELOG("Nothing to read!\n"); /* EOF received. We try to recover a few times, because most likely
exit(EXIT_FAILURE); * i3 just restarted */
ELOG("EOF received, try to recover...\n");
destroy_connection();
reconnect();
return;
} }
rec += n; rec += n;
} }
@ -167,8 +181,12 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) {
* of the message */ * of the message */
char *buffer = malloc(size + 1); char *buffer = malloc(size + 1);
if (buffer == NULL) { if (buffer == NULL) {
ELOG("Could not allocate memory!\n"); /* EOF received. We try to recover a few times, because most likely
exit(EXIT_FAILURE); * i3 just restarted */
ELOG("EOF received, try to recover...\n");
destroy_connection();
reconnect();
return;
} }
rec = 0; rec = 0;
@ -234,7 +252,7 @@ int i3_send_msg(uint32_t type, const char *payload) {
uint32_t written = 0; uint32_t written = 0;
while (to_write > 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) { if (n == -1) {
ELOG("write() failed!\n"); ELOG("write() failed!\n");
exit(EXIT_FAILURE); 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 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)); struct sockaddr_un addr;
ev_io_init(i3_connection, &got_data, sockfd, EV_READ); memset(&addr, 0, sizeof(struct sockaddr_un));
ev_io_start(main_loop, i3_connection); 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; 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 * Subscribe to all the i3-events, we need
* *

View File

@ -215,8 +215,6 @@ int main(int argc, char **argv) {
init_outputs(); init_outputs();
init_connection(socket_path); init_connection(socket_path);
FREE(socket_path);
/* We subscribe to the i3-events we need */ /* We subscribe to the i3-events we need */
subscribe_events(); subscribe_events();
@ -249,6 +247,8 @@ int main(int argc, char **argv) {
kill_child(); kill_child();
FREE(socket_path);
FREE(statusline); FREE(statusline);
clean_xcb(); clean_xcb();