> Date: Wed, 16 Sep 2026 12:55:43 -0400 (EDT) > From: Mouse <[email protected]> > > >> [...] the way the SIGUSR1 handling is coded won't work in general - > >> signal handlers should only ever call async signal safe functions, > >> and neither fopen() nor fclose() is that (fflush() I'm not sure > >> about). > > > This patch can be made safe with a much smaller modification: simply > > keep SIGUSR1 blocked _except_ during the calls to read() and write() > > in dooutput(), when there is no risk of interrupting access to the > > stdio data structures. Just needs a handful of sigprocmask calls. > > That makes it safe...for one particular implementation. It is not safe > in general. There is no promise that stdio is signal-unsafe only when > the signal interrupts a stdio call, though that is the way most > implementations happen to work.
No, it is safe in general for all POSIX-conformant systems: In the presence of signals, all functions defined by this volume of POSIX.1-2024 shall behave as defined when called from or interrupted by a signal-catching function, with the exception that when a signal interrupts an unsafe function or function-like macro, or equivalent (such as the processing equivalent to exit() performed after a return from the initial call to main()), and the signal-catching function calls an unsafe function or function-like macro, the behavior is undefined. POSIX.1-2024, Volume XSH: System Interfaces, Sec. 2.4.3 `Signal Actions' https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_03 In other words, you can safely call a non-async-signal-safe function from a signal handler _if_ you can guarantee that it won't interrupt any non-async-signal-safe function. In contrast, the async-signal-safe functions are _always_ safe to call unconditionally, _even if_ they may be interrupted and the signal handler may call non-async-signal-safe functions (or if they are called from a signal handler that interrupts a non-async-signal-safe function): The following table defines a set of functions and function-like macros that shall be async-signal-safe. Therefore, applications can call them, without restriction, from signal-catching functions. POSIX.1-2024, Volume XSH: System Interfaces, Sec. 2.4.3 `Signal Actions' https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_03 So code like this (pseudo-code, with various irrelevant details elided for brevity) is safe: FILE *fp; on_sigusr1() { int e = errno; /* make sure to save and restore errno! */ fclose(fp); fp = fopen(path, "a"); errno = e; } main() { ... sigprocmask(SIG_BLOCK, {SIGUSR1}, NULL); signal(SIGUSR1, on_sigusr1); ... for (;;) { sigprocmask(SIG_SETMASK, {}, &mask); /* * read and write are async-signal-safe, so they can * safely be interrupted by calls to fclose/fopen */ read(...); write(...); sigprocmask(SIG_SETMASK, &mask, NULL); fwrite(fp, ...); } ... } This isn't new; essentially the same language already appears in POSIX.1-2001, SUSv2 in 1997, and POSIX.1-1990 (all that was added in the excerpt above is clarification about implied calls to unsafe functions like exit() on return from main()), and read() and write() both appear in all the async-signal-safe lists since 1990: POSIX.1-2001, Volume XSH: System Interfaces, Sec. 2.4.3 `Signal Actions' https://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03 Single Unix Specification, Version 2, Volume XSH: System Interfaces, Sec. `sigaction' https://pubs.opengroup.org/onlinepubs/7908799/xsh/sigaction.html POSIX.1-1990, Part I: System API (C Language), Sec. 3.3.1.3 `Signal Actions', pp. 54--55 https://archive.org/details/posix-1/page/n37/mode/1up
