1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
|
From c8de527c0c0ff5b8e2a3c10c1d26e5674ffccf50 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Tue, 24 May 2022 01:27:10 +0800
Subject: [PATCH v2 1/8] Better quit handling
Previous SIGCHLD handler is not async-signal-safe because it calls
exit(), and it also doesn't save-restore errno. Using _exit() will be
async-signal-safe safe but will result in unclean quit. In the end, this
patch will set a flag variable in signal handler, then defer real
cleanup and quitting to main loop.
---
bterm.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/bterm.c b/bterm.c
index d7b574f..605644f 100644
--- a/bterm.c
+++ b/bterm.c
@@ -64,7 +64,7 @@ static const unsigned char palette[16][3] =
static int child_pid = 0;
static struct termios ttysave;
-static int quit = 0;
+static volatile int quit = 0, quit_status = 0;
/* Out of memory. Give up. */
static void out_of_memory (void)
@@ -144,24 +144,29 @@ void send_hangup(void)
void sigchld(int sig)
{
+ int errsv = errno;
int status;
if (waitpid(child_pid, &status, WNOHANG) > 0) {
child_pid = 0;
/* Reset ownership and permissions of ttyfd device? */
tcsetattr(0, TCSAFLUSH, &ttysave);
if (WIFEXITED (status))
- exit(WEXITSTATUS (status));
- if (WIFSIGNALED (status))
- exit(128 + WTERMSIG (status));
- if (WIFSTOPPED (status))
- exit(128 + WSTOPSIG (status));
- exit(status);
+ quit_status = WEXITSTATUS (status);
+ else if (WIFSIGNALED (status))
+ quit_status = 128 + WTERMSIG (status);
+ else if (WIFSTOPPED (status))
+ quit_status = 128 + WSTOPSIG (status);
+ else
+ quit_status = status;
+ quit = 1;
}
signal(SIGCHLD, sigchld);
+ errno = errsv;
}
void sigterm(int sig)
{
+ quit_status = 128 + SIGTERM;
quit = 1;
}
@@ -420,5 +425,5 @@ int main(int argc, char *argv[])
}
}
- return 0;
+ exit(quit_status);
}
--
2.30.2
|