[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[shepherd] 01/03: system: Add support for 'signalfd'.
From: |
Ludovic Courtès |
Subject: |
[shepherd] 01/03: system: Add support for 'signalfd'. |
Date: |
Tue, 26 May 2020 18:10:26 -0400 (EDT) |
civodul pushed a commit to branch master
in repository shepherd.
commit 5920d86cb04b5fb31aca5071f7ba7ec70b8ff891
Author: Ludovic Courtès <address@hidden>
AuthorDate: Sun May 24 16:07:57 2020 +0200
system: Add support for 'signalfd'.
* configure.ac: Add 'AC_CHECK_SIZEOF' calls for 'struct
signalfd_siginfo' and 'sigset_t'. Add 'AC_COMPUTE_INT' for
'SFD_CLOEXEC', 'SIG_BLOCK', and 'SIG_UNBLOCK'. Substitute the results.
* modules/shepherd/system.scm.in (allocate-sigset, sigemptyset)
(sigaddset, sigset): New procedures.
(%sizeof-struct-signalfd-siginfo, SFD_CLOEXEC): New variables.
(signalfd, consume-signalfd-siginfo): New procedures.
(SIG_BLOCK, SIG_UNBLOCK): New variables.
(sigprocmask, block-signals, unblock-signals): New procedures.
---
configure.ac | 18 ++++++++++++
modules/shepherd/system.scm.in | 65 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+)
diff --git a/configure.ac b/configure.ac
index 5d11846..052a826 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,6 +87,24 @@ AC_COMPUTE_INT([PR_SET_CHILD_SUBREAPER],
[PR_SET_CHILD_SUBREAPER], [#include <sy
AC_SUBST([PR_SET_CHILD_SUBREAPER])
AC_MSG_RESULT([done])
+dnl Check the size of 'signalfd_siginfo'. If it's undefined, returns zero.
+AC_CHECK_SIZEOF([struct signalfd_siginfo], [], [#include <sys/signalfd.h>])
+AC_CHECK_SIZEOF([sigset_t], [], [#include <signal.h>])
+
+AC_MSG_CHECKING([<sys/signalfd.h> and <sys/signal.h> constants])
+AC_COMPUTE_INT([SFD_CLOEXEC], [SFD_CLOEXEC], [#include <sys/signalfd.h>])
+AC_COMPUTE_INT([SIG_BLOCK], [SIG_BLOCK], [#include <sys/signal.h>])
+AC_COMPUTE_INT([SIG_UNBLOCK], [SIG_UNBLOCK], [#include <sys/signal.h>])
+AC_MSG_RESULT([done])
+
+SIZEOF_STRUCT_SIGNALFD_SIGINFO="$ac_cv_sizeof_struct_signalfd_siginfo"
+SIZEOF_SIGSET_T="$ac_cv_sizeof_sigset_t"
+AC_SUBST([SIZEOF_STRUCT_SIGNALFD_SIGINFO])
+AC_SUBST([SIZEOF_SIGSET_T])
+AC_SUBST([SFD_CLOEXEC])
+AC_SUBST([SIG_BLOCK])
+AC_SUBST([SIG_UNBLOCK])
+
AC_MSG_CHECKING([whether to build crash handler])
case "$host_os" in
linux-gnu*) build_crash_handler=yes;;
diff --git a/modules/shepherd/system.scm.in b/modules/shepherd/system.scm.in
index e5ecd1f..872fad4 100644
--- a/modules/shepherd/system.scm.in
+++ b/modules/shepherd/system.scm.in
@@ -20,8 +20,10 @@
(define-module (shepherd system)
#:use-module (system foreign)
+ #:use-module (ice-9 binary-ports)
#:use-module (rnrs bytevectors)
#:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-26)
#:export (disable-reboot-on-ctrl-alt-del
reboot
halt
@@ -30,6 +32,11 @@
prctl
PR_SET_CHILD_SUBREAPER
getpgid
+ SFD_CLOEXEC
+ signalfd
+ consume-signalfd-siginfo
+ block-signals
+ unblock-signals
without-automatic-finalization))
;; The <sys/reboot.h> constants.
@@ -132,6 +139,64 @@ ctrlaltdel(8) and see kernel/reboot.c in Linux."
(list err))
result)))))
+(define (allocate-sigset)
+ (bytevector->pointer (make-bytevector @SIZEOF_SIGSET_T@)))
+
+(define sigemptyset
+ (syscall->procedure int "sigemptyset" '(*)))
+
+(define sigaddset
+ (syscall->procedure int "sigaddset" `(* ,int)))
+
+(define (sigset signals)
+ "Return a pointer to a fresh 'sigset_t' for SIGNALS."
+ (let ((set (allocate-sigset)))
+ (sigemptyset set)
+ (for-each (cut sigaddset set <>) signals)
+ set))
+
+(define %sizeof-struct-signalfd-siginfo
+ ;; Size of 'struct signalfd_siginfo' or zero if it doesn't exist, as is the
+ ;; case on GNU/Hurd.
+ @SIZEOF_STRUCT_SIGNALFD_SIGINFO@)
+
+(define SFD_CLOEXEC @SFD_CLOEXEC@)
+
+(define signalfd
+ (let ((proc (syscall->procedure int "signalfd" `(,int * ,int))))
+ (lambda* (fd signals #:optional (flags SFD_CLOEXEC))
+ "Return an open input port over a signal file descriptor for SIGNALS, a
+list of signal constants; if FD is -1, a new file descriptor is allocated,
+otherwise FD is returned and its associated state is updated. FLAGS must be a
+bitmask of SFD_CLOEXEC or SFD_NONBLOCK."
+ (fdopen (proc fd (sigset signals) flags) "r0"))))
+
+(define (consume-signalfd-siginfo port)
+ "Read a 'signalfd_siginfo' structure from PORT and discard it. Return the
+number of the signal received."
+ (let ((bv (get-bytevector-n port %sizeof-struct-signalfd-siginfo)))
+ ;; The first 'uint32_t' field of 'struct signalfd_siginfo' is the signal
+ ;; number.
+ (bytevector-u32-native-ref bv 0)))
+
+(define SIG_BLOCK @SIG_BLOCK@)
+(define SIG_UNBLOCK @SIG_UNBLOCK@)
+
+(define sigprocmask
+ (let ((proc (syscall->procedure int "pthread_sigmask" `(,int * *))))
+ (lambda (how signals)
+ "Add SIGNALS, a list of SIG* values, to the set of blocked signals if
+HOW is SIG_BLOCK, or unblock them if HOW is SIG_UNBLOCK."
+ (proc how (sigset signals) %null-pointer))))
+
+(define (block-signals signals)
+ "Block SIGNALS, a list of SIG* values, in the current thread."
+ (sigprocmask SIG_BLOCK signals))
+
+(define (unblock-signals signals)
+ "Unblock SIGNALS, a list of SIG* values, in the current thread."
+ (sigprocmask SIG_UNBLOCK signals))
+
;;;
;;; Guile shenanigans.