Fix SIGUSR1 handling

Calling ev_break() in a signal handler doesn't work. Instead, we setup a
libev ev_signal handler for this.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2018-11-26 23:56:55 +00:00
parent b89dadec40
commit 531aafabb5
2 changed files with 37 additions and 30 deletions

View File

@ -435,6 +435,7 @@ typedef struct _latom {
#define REG_DATA_INIT { NULL, 0 } #define REG_DATA_INIT { NULL, 0 }
typedef struct ev_session_signal ev_session_signal;
typedef struct ev_session_timer ev_session_timer; typedef struct ev_session_timer ev_session_timer;
typedef struct ev_session_idle ev_session_idle; typedef struct ev_session_idle ev_session_idle;
typedef struct ev_session_prepare ev_session_prepare; typedef struct ev_session_prepare ev_session_prepare;
@ -755,6 +756,8 @@ typedef struct session {
/// so we can be sure if xcb read from X socket at anytime during event /// so we can be sure if xcb read from X socket at anytime during event
/// handling, we will not left any event unhandled in the queue /// handling, we will not left any event unhandled in the queue
ev_session_prepare *event_check; ev_session_prepare *event_check;
/// Signal handler for SIGUSR1
ev_session_signal *usr1_signal;
/// Whether we have hit unredirection timeout. /// Whether we have hit unredirection timeout.
bool tmout_unredir_hit; bool tmout_unredir_hit;
/// Whether we need to redraw the screen /// Whether we need to redraw the screen

View File

@ -53,9 +53,6 @@ cxinerama_upd_scrs(session_t *ps);
static void static void
session_destroy(session_t *ps); session_destroy(session_t *ps);
static void
reset_enable(int __attribute__((unused)) signum);
#ifdef CONFIG_XINERAMA #ifdef CONFIG_XINERAMA
static void static void
cxinerama_upd_scrs(session_t *ps); cxinerama_upd_scrs(session_t *ps);
@ -128,20 +125,25 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
xcb_render_picture_t pict, glx_texture_t *ptex, xcb_render_picture_t pict, glx_texture_t *ptex,
const region_t *reg_paint, const glx_prog_main_t *pprogram); const region_t *reg_paint, const glx_prog_main_t *pprogram);
typedef struct ev_session_timer { struct ev_session_timer {
ev_timer w; ev_timer w;
session_t *ps; session_t *ps;
} ev_session_timer; };
typedef struct ev_session_idle { struct ev_session_idle {
ev_idle w; ev_idle w;
session_t *ps; session_t *ps;
} ev_session_idle; };
typedef struct ev_session_prepare { struct ev_session_prepare {
ev_prepare w; ev_prepare w;
session_t *ps; session_t *ps;
} ev_session_prepare; };
struct ev_session_signal {
ev_signal w;
session_t *ps;
};
// === Global constants === // === Global constants ===
@ -222,8 +224,8 @@ static const char *background_props_str[] = {
// === Global variables === // === Global variables ===
/// Pointer to current session, as a global variable. Only used by /// Pointer to current session, as a global variable. Only used by
/// <code>error()</code> and <code>reset_enable()</code>, which could not /// xerror(), which could not have a pointer to current session passed in.
/// have a pointer to current session passed in. /// XXX Limit what xerror can access by not having this pointer
session_t *ps_g = NULL; session_t *ps_g = NULL;
/** /**
@ -5010,6 +5012,17 @@ x_event_callback(EV_P_ ev_io *w, int revents) {
} }
} }
/**
* Turn on the program reset flag.
*
* This will result in compton resetting itself after next paint.
*/
static void
reset_enable(EV_P_ ev_signal *w, int revents) {
session_t *ps = ((ev_session_signal *)w)->ps;
ev_break(ps->loop, EVBREAK_ALL);
}
/** /**
* Initialize a session. * Initialize a session.
* *
@ -5493,6 +5506,12 @@ session_init(session_t *ps_old, int argc, char **argv) {
ps->delayed_draw_timer->ps = ps; ps->delayed_draw_timer->ps = ps;
ev_init(&ps->delayed_draw_timer->w, delayed_draw_timer_callback); ev_init(&ps->delayed_draw_timer->w, delayed_draw_timer_callback);
// Set up SIGUSR1 signal handler to reset program
ps->usr1_signal = calloc(1, sizeof(ev_session_signal));
ps->usr1_signal->ps = ps;
ev_signal_init(&ps->usr1_signal->w, reset_enable, SIGUSR1);
ev_signal_start(ps->loop, &ps->usr1_signal->w);
// xcb can read multiple events from the socket when a request with reply is // xcb can read multiple events from the socket when a request with reply is
// made. // made.
// //
@ -5761,6 +5780,10 @@ session_destroy(session_t *ps) {
free(ps->event_check); free(ps->event_check);
ps->event_check = NULL; ps->event_check = NULL;
ev_signal_stop(ps->loop, &ps->usr1_signal->w);
free(ps->usr1_signal);
ps->usr1_signal = NULL;
if (ps == ps_g) if (ps == ps_g)
ps_g = NULL; ps_g = NULL;
} }
@ -5798,17 +5821,6 @@ session_run(session_t *ps) {
ev_run(ps->loop, 0); ev_run(ps->loop, 0);
} }
/**
* Turn on the program reset flag.
*
* This will result in compton resetting itself after next paint.
*/
static void
reset_enable(int __attribute__((unused)) signum) {
session_t * const ps = ps_g;
ev_break(ps->loop, EVBREAK_ALL);
}
static void static void
sigint_handler(int __attribute__((unused)) signum) { sigint_handler(int __attribute__((unused)) signum) {
exit(0); exit(0);
@ -5823,16 +5835,8 @@ main(int argc, char **argv) {
// correctly // correctly
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
// Set up SIGUSR1 signal handler to reset program
sigset_t sigmask; sigset_t sigmask;
sigemptyset(&sigmask); sigemptyset(&sigmask);
const struct sigaction usr1_action = {
.sa_handler = reset_enable,
.sa_mask = sigmask,
.sa_flags = 0
};
sigaction(SIGUSR1, &usr1_action, NULL);
const struct sigaction int_action = { const struct sigaction int_action = {
.sa_handler = sigint_handler, .sa_handler = sigint_handler,
.sa_mask = sigmask, .sa_mask = sigmask,