guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[shepherd] 03/05: shepherd: No longer send SIGALRM every second.


From: Ludovic Courtès
Subject: [shepherd] 03/05: shepherd: No longer send SIGALRM every second.
Date: Mon, 20 Apr 2020 16:11:28 -0400 (EDT)

civodul pushed a commit to branch master
in repository shepherd.

commit 03a354e9987383f005b39348ab150608fdfbada9
Author: Ludovic Courtès <address@hidden>
AuthorDate: Mon Apr 20 15:04:58 2020 +0200

    shepherd: No longer send SIGALRM every second.
    
    This kludge was mostly unnecessary since commit
    0ce1076eab9659c29c74bb6aeafb2fec6ef1efd8 on Guile 2.2+.
    
    * modules/shepherd.scm (main): Remove calls to 'sigaction' and 'alarm'.
    Call 'handle-SIGCHLD' each time 'select' returns.
    * modules/shepherd/service.scm (waitpid*): Remove warning in exception
    handler.
    (handle-SIGCHLD): Make 'signum' optional.
    * modules/shepherd/system.scm.in <top level> [guile-2.0]: Replace
    'select'.
    
    fixlet
---
 modules/shepherd.scm           | 26 ++++++++++++++------------
 modules/shepherd/service.scm   | 14 +++++---------
 modules/shepherd/system.scm.in | 17 +++++++++++++++++
 3 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/modules/shepherd.scm b/modules/shepherd.scm
index 3812f8a..704ea47 100644
--- a/modules/shepherd.scm
+++ b/modules/shepherd.scm
@@ -1,5 +1,5 @@
 ;; shepherd.scm -- The daemon shepherd.
-;; Copyright (C) 2013, 2014, 2016, 2018, 2019 Ludovic Courtès <address@hidden>
+;; Copyright (C) 2013, 2014, 2016, 2018, 2019, 2020 Ludovic Courtès 
<address@hidden>
 ;; Copyright (C) 2002, 2003 Wolfgang Jährling <address@hidden>
 ;; Copyright (C) 2018 Carlo Zancanaro <address@hidden>
 ;; Copyright (C) 2018 Danny Milosavljevic <address@hidden>
@@ -255,15 +255,6 @@ socket file at FILE-NAME upon exit of PROC.  Return the 
values of PROC."
                (apply format #f (gettext (cadr args)) (caddr args))
                (quit 1))))
 
-      (when (provided? 'threads)
-        ;; XXX: This terrible hack allows us to make sure that signal handlers
-        ;; get a chance to run in a timely fashion.  Without it, after an 
EINTR,
-        ;; we could restart the accept(2) call below before the corresponding
-        ;; async has been queued.  See the thread at
-        ;; 
<https://lists.gnu.org/archive/html/guile-devel/2013-07/msg00004.html>.
-        (sigaction SIGALRM (lambda _ (alarm 1)))
-        (alarm 1))
-
       ;; Ignore SIGPIPE so that we don't die if a client closes the connection
       ;; prematurely.
       (sigaction SIGPIPE SIG_IGN)
@@ -292,11 +283,22 @@ socket file at FILE-NAME upon exit of PROC.  Return the 
values of PROC."
                     (setvbuf command-source (buffering-mode block) 1024)
                     (process-connection command-source))
                    (_ #f)))
-               (match (select (list sock) (list) (list) (if poll-services? 0.5 
#f))
+
+               ;; XXX: Until we use signalfd(2), there's always a time window
+               ;; before 'select' during which a handler async can be queued
+               ;; but not executed.  Work around it by exiting 'select' every
+               ;; few seconds.
+               (match (select (list sock) (list) (list)
+                              (if poll-services? 0.5 30))
                  (((sock) _ _)
                   (read-from sock))
                  (_
-                  #f))
+                  ;; 'select' returned an empty set, probably due to EINTR.
+                  ;; Explicitly call the SIGCHLD handler because we cannot be
+                  ;; sure the async will be queued and executed before we call
+                  ;; 'select' again.
+                  (handle-SIGCHLD)))
+
                (when poll-services?
                  (check-for-dead-services))
                (next-command))))))))
diff --git a/modules/shepherd/service.scm b/modules/shepherd/service.scm
index 64b0664..8604d2f 100644
--- a/modules/shepherd/service.scm
+++ b/modules/shepherd/service.scm
@@ -880,7 +880,7 @@ false."
                              (default-environment-variables)))
   "Spawn a process that executed COMMAND as per 'exec-command', and return
 its PID."
-  ;; Install the SIGCHLD handler if this is the first fork+exec-command call
+  ;; Install the SIGCHLD handler if this is the first fork+exec-command call.
   (unless %sigchld-handler-installed?
     (sigaction SIGCHLD handle-SIGCHLD SA_NOCLDSTOP)
     (set! %sigchld-handler-installed? #t))
@@ -1063,15 +1063,11 @@ returned in unspecified."
       (lambda ()
         (waitpid what flags))
       (lambda args
-        ;; Did we get ECHILD or something?  If we did, that's a problem,
-        ;; because this procedure is supposed to be called only upon
-        ;; SIGCHLD.
-        (let ((errno (system-error-errno args)))
-          (local-output (l10n "warning: 'waitpid' ~a failed unexpectedly: ~a")
-                        what (strerror errno))
-          '(0 . #f))))))
+        (if (memv (system-error-errno args) (list ECHILD EINTR))
+            '(0 . #f)
+            (apply throw args))))))
 
-(define (handle-SIGCHLD signum)
+(define* (handle-SIGCHLD #:optional (signum SIGCHLD))
   "Handle SIGCHLD, possibly by respawning the service that just died, or
 otherwise by updating its state."
   (let loop ()
diff --git a/modules/shepherd/system.scm.in b/modules/shepherd/system.scm.in
index 5594adf..adf303c 100644
--- a/modules/shepherd/system.scm.in
+++ b/modules/shepherd/system.scm.in
@@ -217,3 +217,20 @@ Turning finalization off shuts down the finalization 
thread as a side effect."
      ;; Nothing to do here: Guile 2.0 does not have a separate finalization
      ;; thread.
      (begin exp ...))))
+
+(cond-expand
+  ((and guile-2 (not guile-2.2))
+   ;; On Guile 2.0, 'select' throws upon EINTR or EAGAIN.  The trick below
+   ;; enables the sane behavior found on 2.2/3.0.
+   (set! select
+     (let ((real-select select))
+       (lambda args
+         (catch 'system-error
+           (lambda ()
+             (apply real-select args))
+           (lambda args
+             (if (memv (system-error-errno args) (list EINTR EAGAIN))
+                 '(() () ())
+                 (apply throw args))))))))
+  (else #t))
+



reply via email to

[Prev in Thread] Current Thread [Next in Thread]