commit 183869fd45813a0be8a778ab29eace9610f41640
parent e8ecbd6089aa0436e5e3544fc43cee14dcfc0d89
Author: Zev Weiss <zev@bewilderbeest.net>
Date: Wed, 15 Oct 2014 02:21:14 -0500
Block terminal signals while handling SelectionRequests.
The intent is to avoid rudely hanging a client that happens to send
a SelectionRequest just as we are about to exit (e.g. due to
receiving SIGALRM while in daemon mode with '-t').
Diffstat:
M | xsel.c | | | 39 | ++++++++++++++++++++++++++++++++++++--- |
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/xsel.c b/xsel.c
@@ -374,6 +374,26 @@ gotpw:
return homedir;
}
+/*
+ * The set of terminal signals we block while handling SelectionRequests.
+ *
+ * If we exit in the middle of handling a SelectionRequest, we might leave the
+ * requesting client hanging, so we try to be nice and finish handling
+ * requests before terminating. Hence we block SIG{ALRM,INT,TERM} while
+ * handling requests and unblock them only while waiting in XNextEvent().
+ */
+static sigset_t exit_sigs;
+
+static void block_exit_sigs(void)
+{
+ sigprocmask (SIG_BLOCK, &exit_sigs, NULL);
+}
+
+static void unblock_exit_sigs(void)
+{
+ sigprocmask (SIG_UNBLOCK, &exit_sigs, NULL);
+}
+
/* The jmp_buf to longjmp out of the signal handler */
static sigjmp_buf env_alrm;
@@ -1713,12 +1733,16 @@ set_selection (Atom selection, unsigned char * sel)
{
XEvent event;
IncrTrack * it;
-
+
if (own_selection (selection) == False) return;
for (;;) {
+ /* Flush before unblocking signals so we send replies before exiting */
+ XFlush (display);
+ unblock_exit_sigs ();
XNextEvent (display, &event);
-
+ block_exit_sigs ();
+
switch (event.type) {
case SelectionClear:
if (event.xselectionclear.selection == selection) return;
@@ -1799,8 +1823,12 @@ set_selection_pair (unsigned char * sel_p, unsigned char * sel_s)
}
for (;;) {
+ /* Flush before unblocking signals so we send replies before exiting */
+ XFlush (display);
+ unblock_exit_sigs ();
XNextEvent (display, &event);
-
+ block_exit_sigs ();
+
switch (event.type) {
case SelectionClear:
if (event.xselectionclear.selection == XA_PRIMARY) {
@@ -2214,6 +2242,11 @@ main(int argc, char *argv[])
*/
compound_text_atom = XInternAtom (display, "COMPOUND_TEXT", False);
+ sigemptyset (&exit_sigs);
+ sigaddset (&exit_sigs, SIGALRM);
+ sigaddset (&exit_sigs, SIGINT);
+ sigaddset (&exit_sigs, SIGTERM);
+
/* handle selection keeping and exit if so */
if (do_keep) {
keep_selections ();