Re: [i3] [PATCH] Use ev_break() rather than exit() in i3bar.

  • From: DR <drdarkraven@xxxxxxxxx>
  • To: "Discussions/Questions about the i3 window manager" <i3-discuss@xxxxxxxxxxxxx>
  • Date: Sat, 3 Mar 2012 20:47:29 +0800

On Sat, Mar 3, 2012 at 8:29 PM, DR <drdarkraven@xxxxxxxxx> wrote:

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.

Sorry, sorry. I made a mistake, I leave out a file in this patch.

New patch attached.
From a7b0dab8b4f49b5c9a48e3a37f278f1f552ba4a3 Mon Sep 17 00:00:00 2001
From: darkraven <drdarkraven@xxxxxxxxx>
Date: Sat, 3 Mar 2012 20:45:35 +0800
Subject: [PATCH] Convert exit() to ev_break(), so i3bar could exit cleanly,
esp. when i3bar is in hide mode

---
i3bar/include/common.h | 9 +++++----
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 ++++--
7 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/i3bar/include/common.h b/i3bar/include/common.h
index 212b9dd..934c751 100644
--- a/i3bar/include/common.h
+++ b/i3bar/include/common.h
@@ -15,9 +15,10 @@

typedef struct rect_t rect;

-struct ev_loop* main_loop;
-char *statusline;
-char *statusline_buffer;
+extern struct ev_loop* main_loop;
+extern char *statusline;
+extern char *statusline_buffer;
+extern int return_status;

struct rect_t {
int x;
@@ -45,7 +46,7 @@ struct status_block {
TAILQ_ENTRY(status_block) blocks;
};

-TAILQ_HEAD(statusline_head, status_block) statusline_head;
+extern TAILQ_HEAD(statusline_head, status_block) statusline_head;

#include "child.h"
#include "ipc.h"
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

Other related posts: