If i3bar is running in hide mode, when i3wm exit, i3bar will exit without killing its child process, leaving a couple of processes in 'T' mode (i.e. Stopped).
With this patch, when i3bar needs to quit, it will call ev_break() rather than exit(), thus gives the code after ev_loop() a chance to clean things up. I'm not very sure I've done things right. I might change some exit()s called before ev_loop() into ev_break(), or leave some exit()s unconverted. Someone please review this patch.
From 9cdd4ad0d84c20efe1824a609995b368322f5eb2 Mon Sep 17 00:00:00 2001 From: darkraven <[email protected]> Date: Sat, 3 Mar 2012 20:22:06 +0800 Subject: [PATCH] Convert exit() to ev_break(), so i3bar could exit cleanly, esp. when i3bar is in hide mode --- i3bar/src/child.c | 10 ++++++++-- i3bar/src/ipc.c | 33 ++++++++++++++++++++++++--------- i3bar/src/main.c | 7 +++++-- i3bar/src/outputs.c | 3 ++- i3bar/src/workspaces.c | 3 ++- i3bar/src/xcb.c | 6 ++++-- 6 files changed, 45 insertions(+), 17 deletions(-) diff --git a/i3bar/src/child.c b/i3bar/src/child.c index c98befb..596e89d 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -37,6 +37,8 @@ bool plaintext = false; yajl_callbacks callbacks; yajl_handle parser; +char *statusline; + typedef struct parser_ctx { /* A copy of the last JSON map key. */ char *last_map_key; @@ -162,12 +164,16 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { /* finish up */ break; } - ELOG("read() failed!: %s\n", strerror(errno)); - exit(EXIT_FAILURE); + ELOG("read() failed!: %s\n", strerror(errno)) + return_status = EXIT_FAILURE; + ev_break(main_loop, EVBREAK_ALL); + FREE(buffer); + return; } if (n == 0) { /* end of file, kill the watcher */ ELOG("stdin: received EOF\n"); + FREE(buffer); cleanup(); draw_bars(); return; diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index 8f8174e..1675eb6 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -144,6 +144,7 @@ handler_t event_handlers[] = { void got_data(struct ev_loop *loop, ev_io *watcher, int events) { DLOG("Got data!\n"); int fd = watcher->fd; + char *buffer = NULL; /* First we only read the header, because we know its length */ uint32_t header_len = strlen(I3_IPC_MAGIC) + sizeof(uint32_t)*2; @@ -156,14 +157,15 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { int n = read(fd, header + rec, header_len - rec); if (n == -1) { ELOG("read() failed: %s\n", strerror(errno)); - exit(EXIT_FAILURE); + return_status = EXIT_FAILURE; + goto got_data_end; } if (n == 0) { /* EOF received. Since i3 will restart i3bar instances as appropriate, * we exit here. */ - DLOG("EOF received, exiting...\n"); - clean_xcb(); - exit(EXIT_SUCCESS); + ELOG("EOF received, exiting...\n"); + return_status = EXIT_SUCCESS; + goto got_data_end; } rec += n; } @@ -173,7 +175,8 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { (int) strlen(I3_IPC_MAGIC), header, I3_IPC_MAGIC); - exit(EXIT_FAILURE); + return_status = EXIT_FAILURE; + goto got_data_end; } char *walk = header + strlen(I3_IPC_MAGIC); @@ -185,18 +188,20 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { /* Now that we know, what to expect, we can start read()ing the rest * of the message */ - char *buffer = smalloc(size + 1); + buffer = smalloc(size + 1); rec = 0; while (rec < size) { int n = read(fd, buffer + rec, size - rec); if (n == -1) { ELOG("read() failed: %s\n", strerror(errno)); - exit(EXIT_FAILURE); + return_status = EXIT_FAILURE; + goto got_data_end; } if (n == 0) { ELOG("Nothing to read!\n"); - exit(EXIT_FAILURE); + return_status = EXIT_FAILURE; + goto got_data_end; } rec += n; } @@ -213,6 +218,13 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { FREE(header); FREE(buffer); + return; + +got_data_end: + FREE(header); + FREE(buffer); + ev_break(main_loop, EVBREAK_ALL); + return; } /* @@ -250,7 +262,10 @@ int i3_send_msg(uint32_t type, const char *payload) { int n = write(i3_connection->fd, buffer + written, to_write); if (n == -1) { ELOG("write() failed: %s\n", strerror(errno)); - exit(EXIT_FAILURE); + FREE(buffer); + return_status = EXIT_FAILURE; + ev_break(main_loop, EVBREAK_ALL); + return 1; } to_write -= n; diff --git a/i3bar/src/main.c b/i3bar/src/main.c index e648e00..2c32955 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -17,6 +17,8 @@ #include "common.h" +struct ev_loop *main_loop; +int return_status; /* * Glob path, i.e. expand ~ * @@ -148,7 +150,8 @@ int main(int argc, char **argv) { /* From here on everything should run smooth for itself, just start listening for * events. We stop simply stop the event-loop, when we are finished */ - ev_loop(main_loop, 0); + return_status = EXIT_SUCCESS; + ev_run(main_loop, 0); kill_child(); @@ -159,5 +162,5 @@ int main(int argc, char **argv) { free_workspaces(); - return 0; + return return_status; } diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c index 9dc5cab..6ad72f8 100644 --- a/i3bar/src/outputs.c +++ b/i3bar/src/outputs.c @@ -300,7 +300,8 @@ void parse_outputs_json(char *json) { #endif case yajl_status_error: ELOG("Could not parse outputs-reply!\n"); - exit(EXIT_FAILURE); + return_status = EXIT_FAILURE; + ev_break(main_loop, EVBREAK_ALL); break; } diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index 5df1899..a6a326c 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -256,7 +256,8 @@ void parse_workspaces_json(char *json) { #endif case yajl_status_error: ELOG("Could not parse workspaces-reply!\n"); - exit(EXIT_FAILURE); + return_status = EXIT_FAILURE; + ev_break(main_loop, EVBREAK_ALL); break; } diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 2b173ee..1541533 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -214,7 +214,8 @@ void unhide_bars() { values); if (xcb_request_failed(cookie, "Could not reconfigure window")) { - exit(EXIT_FAILURE); + return_status = EXIT_FAILURE; + ev_break(main_loop, EVBREAK_ALL); } xcb_map_window(xcb_connection, walk->bar); } @@ -681,7 +682,8 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) { if (xcb_connection_has_error(xcb_connection)) { ELOG("X11 connection was closed unexpectedly - maybe your X server terminated / crashed?\n"); - exit(1); + return_status = EXIT_FAILURE; + ev_break(main_loop, EVBREAK_ALL); } while ((event = xcb_poll_for_event(xcb_connection)) != NULL) { -- 1.7.9.2
