From fdadf577e9ea64c8a5df7a2773cccec5e37be928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 7 Jan 2019 18:27:43 +0100 Subject: [PATCH] main: detect when X server dies, and abort This is done by creating an XCB connection, whose only purpose is to detect a POLLHUP (xcb disconncet). Furthermore, make sure SIGINT is blocked in all threads except the main thread. --- main.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index f9164d7..9c4d86c 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -115,18 +116,55 @@ main(int argc, const char *const *argv) .abort_fd = abort_fd, }; + /* Block SIGINT (this is under the assumption that threads inherit + * the signal mask */ + sigset_t signal_mask; + sigemptyset(&signal_mask); + sigaddset(&signal_mask, SIGINT); + pthread_sigmask(SIG_BLOCK, &signal_mask, NULL); + thrd_t bar_thread; thrd_create(&bar_thread, (int (*)(void *))bar->run, &bar_ctx); + /* Now unblock. We should be only thread receiving SIGINT */ + pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL); + + /* Connect to XCB, to be able to detect a disconnect (allowing us + * to exit) */ + xcb_connection_t *xcb = xcb_connect(NULL, NULL); + assert(xcb != NULL); + + /* Wait for SIGINT, or XCB disconnect */ while (!aborted) { - sleep(999999999); + struct pollfd fds[] = { + {.fd = xcb_get_file_descriptor(xcb), .events = POLLPRI} + }; + + poll(fds, 1, -1); + + if (aborted) + break; + + LOG_INFO("XCB poll data"); + + if (fds[0].revents & POLLHUP) { + LOG_INFO("disconnected from XCB, exiting"); + break; + } } - /* Signal abort to all workers */ + xcb_disconnect(xcb); + + if (aborted) + LOG_INFO("aborted"); + + /* Signal abort to other threads */ write(abort_fd, &(uint64_t){1}, sizeof(uint64_t)); int res; - thrd_join(bar_thread, &res); + int r = thrd_join(bar_thread, &res); + if (r != 0) + LOG_ERRNO_P("failed to join bar thread", r); bar->destroy(bar); yml_destroy(conf);