process-util: Add helpers to check for signal handler presence

Add new pidref_has_sigcgt() and pidref_has_sigblk() helpers. These read
the SigCgt and SigBlk bitmasks from /proc/<pid>/status to detect either
traditional signal handlers installed via sigaction(2), or blocked signals
that are typically handled via signalfd(2), such as through
sd_event_add_signal().

Both mechanisms represent valid ways to handle a signal without invoking
the default action. Share the parsing and pidref verification between the
two public helpers.
This commit is contained in:
Chris Down
2026-08-04 16:51:37 -07:00
parent 91d2131e20
commit b64b996119
2 changed files with 50 additions and 0 deletions
+48
View File
@@ -21,6 +21,7 @@
#include "alloc-util.h"
#include "architecture.h"
#include "argv-util.h"
#include "bitfield.h"
#include "capability-util.h"
#include "cgroup-util.h"
#include "dirent-util.h"
@@ -804,6 +805,53 @@ int get_process_umask(pid_t pid, mode_t *ret) {
return parse_mode(m, ret);
}
static int pid_get_sigmask(pid_t pid, const char *field_name, uint64_t *ret) {
_cleanup_free_ char *field = NULL;
int r;
assert(pid >= 0);
assert(field_name);
assert(ret);
r = procfs_file_get_field(pid, "status", field_name, &field);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
return safe_atou64_full(field, 16, ret);
}
static int pidref_has_sigmask(const PidRef *pidref, int sig, const char *field_name) {
uint64_t mask;
int r;
if (!pidref_is_set(pidref))
return -ESRCH;
if (pidref_is_remote(pidref))
return -EREMOTE;
if (!SIGNAL_VALID(sig))
return -EINVAL;
r = pid_get_sigmask(pidref->pid, field_name, &mask);
if (r < 0)
return r;
r = pidref_verify(pidref);
if (r < 0)
return r;
return BIT_SET(mask, sig - 1);
}
int pidref_has_sigcgt(const PidRef *pidref, int sig) {
return pidref_has_sigmask(pidref, sig, "SigCgt");
}
int pidref_has_sigblk(const PidRef *pidref, int sig) {
return pidref_has_sigmask(pidref, sig, "SigBlk");
}
/*
* Return values:
* < 0 : pidref_wait_for_terminate() failed to get the state of the
+2
View File
@@ -53,6 +53,8 @@ int pidref_get_ppid_as_pidref(const PidRef *pidref, PidRef *ret);
int pid_get_start_time(pid_t pid, usec_t *ret);
int pidref_get_start_time(const PidRef *pid, usec_t *ret);
int get_process_umask(pid_t pid, mode_t *ret);
int pidref_has_sigcgt(const PidRef *pidref, int sig);
int pidref_has_sigblk(const PidRef *pidref, int sig);
static inline bool SIGINFO_CODE_IS_DEAD(int code) {
return IN_SET(code, CLD_EXITED, CLD_KILLED, CLD_DUMPED);