Simplify by using Gnulib sigaction

* bootstrap.conf (gnulib_modules): Add raise, sigaction, signal-h,
sigprocmask.  Remove signal.
* configure.ac: Do not check for raise, sigaction, sigprocmask,
sigsetmask.
* src/patch.c (main): Do not block signals during dry runs; there's
no need.
* src/util.c (SIGCHLD, raise, sigset_t, sigemptyset, sigmask)
(sigaddset, sigismember, sigprocmask, sigblock, sigsetmask):
Remove substitutes; not needed now that we have Gnulib.
(sigs): Don’t worry about whether SIGHUP and SIGPIPE are present.
(NUM_SIGS): Now a constant, not a macro.
(signals_to_block): Remove.  All uses changed to fatal_act.sa_mask.
(fatal_exit_handler) [!HAVE_SIGACTION]: Remove.  All uses removed.
(init_signals): Rename from set_signals.  All uses changed.
Only do the true part; the false part is now done by unblock_signals.
(block_signals): Rename from ignore_signals, since it now blocks
instead of ignoring on all platforms.  All uses changed.
(init_signals, block_signals): Simplify by assuming
HAVE_SIGACTION, HAVE_SIGPROCMASK, HAVE_SIGSETMASK.
(setup_handler): Remove macro.
(unblock_signals): New function.
This commit is contained in:
Paul Eggert 2024-08-25 10:12:05 -07:00
parent d3816ac315
commit abf6fb176b
6 changed files with 49 additions and 105 deletions

View File

@ -56,11 +56,14 @@ openat
parse-datetime
progname
quotearg
raise
readlinkat
realloc-gnu
renameat
setenv
signal
sigaction
signal-h
sigprocmask
size_max
ssize_t
stat-time

View File

@ -138,7 +138,7 @@ AC_TYPE_OFF_T
gl_SIZE_MAX
gl_FUNC_XATTR
AC_CHECK_FUNCS(geteuid getuid raise sigaction sigprocmask sigsetmask)
AC_CHECK_FUNCS_ONCE([geteuid getuid])
AC_FUNC_SETMODE_DOS
AC_PATH_PROG([ED], [ed], [ed])

View File

@ -71,15 +71,19 @@
# parse-datetime \
# progname \
# quotearg \
# raise \
# readlinkat \
# realloc-gnu \
# renameat \
# setenv \
# signal \
# sigaction \
# signal-h \
# sigprocmask \
# size_max \
# ssize_t \
# stat-time \
# stdbool \
# stdckdint \
# stdlib \
# symlinkat \
# sys_stat \
@ -92,7 +96,8 @@
# verror \
# xalloc \
# xlist \
# xmemdup0
# xmemdup0 \
# year2038-recommended
AUTOMAKE_OPTIONS = 1.14 gnits subdir-objects

View File

@ -226,7 +226,7 @@ main (int argc, char **argv)
outstate.ofp = open_outfile (outfile);
/* Make sure we clean up in case of disaster. */
set_signals (false);
init_signals ();
/* When the file to patch is specified on the command line, allow that file
to lie outside the current working tree. Still doesn't allow to follow
@ -584,8 +584,10 @@ main (int argc, char **argv)
}
}
if (!dry_run)
block_signals ();
/* and put the output where desired */
ignore_signals ();
if (! skip_rest_of_patch && ! outfile) {
bool backup = make_backups
|| (backup_if_mismatch && (mismatch | failed));
@ -743,7 +745,8 @@ main (int argc, char **argv)
say ("\n");
}
}
set_signals (true);
if (!dry_run)
unblock_signals ();
}
if (outstate.ofp && (ferror (outstate.ofp) || fclose (outstate.ofp) != 0))
write_fatal ();

View File

@ -31,13 +31,6 @@
#include "error.h"
#include <signal.h>
#if !defined SIGCHLD && defined SIGCLD
#define SIGCHLD SIGCLD
#endif
#if ! HAVE_RAISE && ! defined raise
# define raise(sig) kill (getpid (), sig)
#endif
#include <stdarg.h>
#include <stdckdint.h>
@ -1125,14 +1118,9 @@ ok_to_reverse (char const *format, ...)
/* How to handle certain events when not in a critical region. */
#define NUM_SIGS ((int) (sizeof (sigs) / sizeof (*sigs)))
static int const sigs[] = {
#ifdef SIGHUP
SIGHUP,
#endif
#ifdef SIGPIPE
SIGPIPE,
#endif
#ifdef SIGTERM
SIGTERM,
#endif
@ -1144,104 +1132,48 @@ static int const sigs[] = {
#endif
SIGINT
};
enum { NUM_SIGS = sizeof sigs / sizeof *sigs };
#if !HAVE_SIGPROCMASK
#define sigset_t int
#define sigemptyset(s) (*(s) = 0)
#ifndef sigmask
#define sigmask(sig) (1 << ((sig) - 1))
#endif
#define sigaddset(s, sig) (*(s) |= sigmask (sig))
#define sigismember(s, sig) ((*(s) & sigmask (sig)) != 0)
#define sigprocmask(how, n, o) \
((how) == SIG_BLOCK \
? ((o) ? *(o) = sigblock (*(n)) : sigblock (*(n))) \
: (how) == SIG_UNBLOCK \
? sigsetmask (((o) ? *(o) = sigblock (0) : sigblock (0)) & ~*(n)) \
: (o ? *(o) = sigsetmask (*(n)) : sigsetmask (*(n))))
#if !HAVE_SIGSETMASK
#define sigblock(mask) 0
#define sigsetmask(mask) 0
#endif
#endif
/* The initial signal mask for the process. */
static sigset_t initial_signal_mask;
static sigset_t signals_to_block;
#if ! HAVE_SIGACTION
static void fatal_exit_handler (int) __attribute__ ((noreturn));
static void
fatal_exit_handler (int sig)
{
signal (sig, SIG_IGN);
fatal_exit (sig);
}
#endif
/* How to handle signals. fatal_act.sa_mask lists signals to be
blocked when handling signals or in a critical section. */
static struct sigaction fatal_act;
void
set_signals (bool reset)
init_signals (void)
{
int i;
#if HAVE_SIGACTION
struct sigaction initial_act, fatal_act;
/* System V fork+wait does not work if SIGCHLD is ignored. */
signal (SIGCHLD, SIG_DFL);
fatal_act.sa_handler = fatal_exit;
sigemptyset (&fatal_act.sa_mask);
fatal_act.sa_flags = 0;
#define setup_handler(sig) sigaction (sig, &fatal_act, (struct sigaction *) 0)
#else
#define setup_handler(sig) signal (sig, fatal_exit_handler)
#endif
for (int i = 0; i < NUM_SIGS; i++)
{
struct sigaction initial_act;
if (sigaction (sigs[i], NULL, &initial_act) == 0
&& initial_act.sa_handler != SIG_IGN)
sigaddset (&fatal_act.sa_mask, sigs[i]);
}
if (!reset)
{
#ifdef SIGCHLD
/* System V fork+wait does not work if SIGCHLD is ignored. */
signal (SIGCHLD, SIG_DFL);
#endif
sigemptyset (&signals_to_block);
for (i = 0; i < NUM_SIGS; i++)
{
bool ignoring_signal;
#if HAVE_SIGACTION
if (sigaction (sigs[i], (struct sigaction *) 0, &initial_act) != 0)
continue;
ignoring_signal = initial_act.sa_handler == SIG_IGN;
#else
ignoring_signal = signal (sigs[i], SIG_IGN) == SIG_IGN;
#endif
if (! ignoring_signal)
{
sigaddset (&signals_to_block, sigs[i]);
setup_handler (sigs[i]);
}
}
}
else
{
/* Undo the effect of ignore_signals. */
#if HAVE_SIGPROCMASK || HAVE_SIGSETMASK
sigprocmask (SIG_SETMASK, &initial_signal_mask, (sigset_t *) 0);
#else
for (i = 0; i < NUM_SIGS; i++)
if (sigismember (&signals_to_block, sigs[i]))
setup_handler (sigs[i]);
#endif
}
for (int i = 0; i < NUM_SIGS; i++)
if (sigismember (&fatal_act.sa_mask, sigs[i]))
sigaction (sigs[i], &fatal_act, NULL);
}
/* How to handle certain events when in a critical region. */
void
ignore_signals (void)
block_signals (void)
{
#if HAVE_SIGPROCMASK || HAVE_SIGSETMASK
sigprocmask (SIG_BLOCK, &signals_to_block, &initial_signal_mask);
#else
int i;
for (i = 0; i < NUM_SIGS; i++)
if (sigismember (&signals_to_block, sigs[i]))
signal (sigs[i], SIG_IGN);
#endif
sigprocmask (SIG_BLOCK, &fatal_act.sa_mask, &initial_signal_mask);
}
void
unblock_signals (void)
{
sigprocmask (SIG_BLOCK, &initial_signal_mask, NULL);
}
void
@ -1251,7 +1183,7 @@ exit_with_signal (int sig)
signal (sig, SIG_DFL);
sigemptyset (&s);
sigaddset (&s, sig);
sigprocmask (SIG_UNBLOCK, &s, (sigset_t *) 0);
sigprocmask (SIG_UNBLOCK, &s, NULL);
raise (sig);
exit (2);
}

View File

@ -53,7 +53,9 @@ void copy_file (char const *, struct stat const *,
char const *, struct stat *, int, mode_t, bool);
void append_to_file (char const *, char const *);
void exit_with_signal (int) __attribute__ ((noreturn));
void ignore_signals (void);
void init_signals (void);
void block_signals (void);
void unblock_signals (void);
void init_backup_hash_table (void);
void init_time (void);
void xalloc_die (void) __attribute__ ((noreturn));
@ -62,7 +64,6 @@ void move_file (char const *, bool *, struct stat const *, char const *, mode_t,
void read_fatal (void) __attribute__ ((noreturn));
void remove_prefix (char *, size_t);
void removedirs (char const *);
void set_signals (bool);
void write_fatal (void) __attribute__ ((noreturn));
void insert_file_id (struct stat const *, enum file_id_type);
enum file_id_type lookup_file_id (struct stat const *);