sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

st-background-image-signal-reload-0.8.5.diff (3333B)


      1 From b56c9081dc4c62b7de5357cc73bc10a310f011b8 Mon Sep 17 00:00:00 2001
      2 From: Matthias Schoth <mschoth@gmail.com>
      3 Date: Sun, 17 Apr 2022 04:01:59 +0200
      4 Subject: [PATCH] Reload background image on USR1 signal.
      5 
      6 Queue reload requests from the signal handler and service them from the
      7 main loop. Xlib is not async-signal-safe, so calling it directly from the
      8 handler can crash st or leak X resources when signals arrive while st is
      9 drawing.
     10 ---
     11  x.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
     12  1 file changed, 55 insertions(+), 1 deletion(-)
     13 
     14 diff --git a/x.c b/x.c
     15 index cab0058..7c9076c 100644
     16 --- a/x.c
     17 +++ b/x.c
     18 @@ -1,5 +1,6 @@
     19  /* See LICENSE for license details. */
     20  #include <errno.h>
     21 +#include <fcntl.h>
     22  #include <math.h>
     23  #include <limits.h>
     24  #include <locale.h>
     25 @@ -157,6 +158,8 @@ static int xicdestroy(XIC, XPointer, XPointer);
     26  static void xinit(int, int);
     27  static void updatexy(void);
     28  static XImage *loadff(const char *);
     29 +static void bgreload(int);
     30 +static void bgreloadinit(void);
     31  static void bginit();
     32  static void cresize(int, int);
     33  static void xresize(int, int);
     34 @@ -1319,6 +1322,46 @@ loadff(const char *filename)
     35  	return xi;
     36  }
     37  
     38 +static int bgreloadpipe[2] = {-1, -1};
     39 +
     40 +/*
     41 + * Xlib is not async-signal-safe, so just wake up the main loop and let it
     42 + * reload the image there.
     43 + */
     44 +static void
     45 +bgreload(int sig)
     46 +{
     47 +	char c = 0;
     48 +
     49 +	(void)sig;
     50 +	if (bgreloadpipe[1] != -1)
     51 +		(void)write(bgreloadpipe[1], &c, 1);
     52 +}
     53 +
     54 +static void
     55 +bgreloadinit(void)
     56 +{
     57 +	struct sigaction sa;
     58 +	int flags;
     59 +
     60 +	if (pipe(bgreloadpipe) < 0)
     61 +		die("pipe: %s\n", strerror(errno));
     62 +
     63 +	flags = fcntl(bgreloadpipe[0], F_GETFL);
     64 +	fcntl(bgreloadpipe[0], F_SETFL, flags | O_NONBLOCK);
     65 +	flags = fcntl(bgreloadpipe[1], F_GETFL);
     66 +	fcntl(bgreloadpipe[1], F_SETFL, flags | O_NONBLOCK);
     67 +	fcntl(bgreloadpipe[0], F_SETFD, FD_CLOEXEC);
     68 +	fcntl(bgreloadpipe[1], F_SETFD, FD_CLOEXEC);
     69 +
     70 +	memset(&sa, 0, sizeof(sa));
     71 +	sa.sa_handler = bgreload;
     72 +	sigemptyset(&sa.sa_mask);
     73 +	sa.sa_flags = SA_RESTART;
     74 +	if (sigaction(SIGUSR1, &sa, NULL) < 0)
     75 +		die("sigaction: %s\n", strerror(errno));
     76 +}
     77 +
     78  /*
     79   * initialize background image
     80   */
     81 @@ -2046,6 +2089,8 @@ run(void)
     82  	int w = win.w, h = win.h;
     83  	fd_set rfd;
     84  	int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing;
     85 +	int bgrfd = bgreloadpipe[0];
     86 +	char c;
     87  	struct timespec seltv, *tv, now, lastblink, trigger;
     88  	double timeout;
     89  
     90 @@ -2072,6 +2117,7 @@ run(void)
     91  		FD_ZERO(&rfd);
     92  		FD_SET(ttyfd, &rfd);
     93  		FD_SET(xfd, &rfd);
     94 +		FD_SET(bgrfd, &rfd);
     95  
     96  		if (XPending(xw.dpy))
     97  			timeout = 0;  /* existing events might not set xfd */
     98 @@ -2080,13 +2126,20 @@ run(void)
     99  		seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec);
    100  		tv = timeout >= 0 ? &seltv : NULL;
    101  
    102 -		if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) {
    103 +		if (pselect(MAX(xfd, MAX(ttyfd, bgrfd))+1, &rfd, NULL, NULL, tv, NULL) < 0) {
    104  			if (errno == EINTR)
    105  				continue;
    106  			die("select failed: %s\n", strerror(errno));
    107  		}
    108  		clock_gettime(CLOCK_MONOTONIC, &now);
    109  
    110 +		if (FD_ISSET(bgrfd, &rfd)) {
    111 +			while (read(bgrfd, &c, 1) > 0)
    112 +				;
    113 +			bginit();
    114 +			redraw();
    115 +		}
    116 +
    117  		if (FD_ISSET(ttyfd, &rfd))
    118  			ttyread();
    119  
    120 @@ -2219,6 +2272,7 @@ run:
    121  	rows = MAX(rows, 1);
    122  	tnew(cols, rows);
    123  	xinit(cols, rows);
    124 +	bgreloadinit();
    125  	bginit();
    126  	xsetenv();
    127  	selinit();
    128 -- 
    129 2.55.0
    130