[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[shepherd] 02/02: Handle forked process SIGCHLD signals.
From: |
Ludovic Courtès |
Subject: |
[shepherd] 02/02: Handle forked process SIGCHLD signals. |
Date: |
Sun, 4 Mar 2018 17:01:35 -0500 (EST) |
civodul pushed a commit to branch master
in repository shepherd.
commit ff7cef96aefae60eaf9448e3050cadd8dc4a7694
Author: Carlo Zancanaro <address@hidden>
Date: Sun Mar 4 07:46:13 2018 +1100
Handle forked process SIGCHLD signals.
* tests/forking-service.sh: New file.
* Makefile.am (TESTS): Add tests/forking-service.sh.
* modules/shepherd.scm: Set the child subreaper attribute of main shepherd
process (as long as we're not pid 1).
* modules/shepherd/service.scm (root-service)[daemonize]: Set the child
subreaper attribute of newly forked shepherd process.
Signed-off-by: Ludovic Courtès <address@hidden>
---
Makefile.am | 1 +
modules/shepherd.scm | 7 +++
modules/shepherd/service.scm | 4 +-
tests/forking-service.sh | 112 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index eafa308..8dad006 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -190,6 +190,7 @@ TESTS = \
tests/no-home.sh \
tests/pid-file.sh \
tests/status-sexp.sh \
+ tests/forking-service.sh \
tests/signals.sh
TEST_EXTENSIONS = .sh
diff --git a/modules/shepherd.scm b/modules/shepherd.scm
index df5420f..faa1e47 100644
--- a/modules/shepherd.scm
+++ b/modules/shepherd.scm
@@ -51,6 +51,13 @@
(define (main . args)
(initialize-cli)
+ (when (not (= 1 (getpid)))
+ ;; Register for orphaned processes to be reparented onto us when their
+ ;; original parent dies. This lets us handle SIGCHLD from daemon processes
+ ;; that would otherwise have been reparented under pid 1. This is
+ ;; unnecessary when we are pid 1.
+ (catch-system-error (prctl PR_SET_CHILD_SUBREAPER 1)))
+
(let ((config-file #f)
(socket-file default-socket-file)
(pid-file #f)
diff --git a/modules/shepherd/service.scm b/modules/shepherd/service.scm
index 2224932..b6394f2 100644
--- a/modules/shepherd/service.scm
+++ b/modules/shepherd/service.scm
@@ -1274,7 +1274,9 @@ we want to receive these signals."
(local-output "Running as PID 1, so not daemonizing."))
(else
(if (zero? (primitive-fork))
- #t
+ (begin
+ (catch-system-error (prctl PR_SET_CHILD_SUBREAPER 1))
+ #t)
(primitive-exit 0))))))
(persistency
"Safe the current state of running and non-running services.
diff --git a/tests/forking-service.sh b/tests/forking-service.sh
new file mode 100644
index 0000000..446a6d1
--- /dev/null
+++ b/tests/forking-service.sh
@@ -0,0 +1,112 @@
+# GNU Shepherd --- Test detecting a forked process' termination
+# Copyright © 2016 Ludovic Courtès <address@hidden>
+# Copyright © 2018 Carlo Zancanaro <address@hidden>
+#
+# This file is part of the GNU Shepherd.
+#
+# The GNU Shepherd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or (at
+# your option) any later version.
+#
+# The GNU Shepherd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the GNU Shepherd. If not, see <http://www.gnu.org/licenses/>.
+
+shepherd --version
+herd --version
+
+socket="t-socket-$$"
+conf="t-conf-$$"
+log="t-log-$$"
+pid="t-pid-$$"
+service_pid="t-service-pid-$$"
+service2_pid="t-service2-pid-$$"
+service2_started="t-service2-starts-$$"
+
+herd="herd -s $socket"
+
+function cleanup
+{
+ cat $log || true
+ rm -f $socket $conf $log $service2_started
+ test -f $pid && kill "`cat $pid`" || true
+ rm -f $pid
+ test -f $service_pid && kill "`cat $service_pid`" || true
+ rm -f $service_pid
+ test -f $service2_pid && kill "`cat $service2_pid`" || true
+ rm -f $service2_pid
+}
+
+trap cleanup EXIT
+
+cat > "$conf"<<EOF
+(define %command
+ '("$SHELL" "-c" "sleep 600 & echo \$! > $PWD/$service_pid"))
+
+(register-services
+ (make <service>
+ ;; A service that forks into a different process.
+ #:provides '(test)
+ #:start (make-forkexec-constructor %command
+ #:pid-file "$PWD/$service_pid")
+ #:stop (make-kill-destructor)
+ #:respawn? #f))
+
+(define %command2
+ '("$SHELL" "-c" "echo started >> $PWD/$service2_started; sleep 600 & echo
\$! > $PWD/$service2_pid"))
+
+(register-services
+ (make <service>
+ ;; A service that forks into a different process.
+ #:provides '(test2)
+ #:start (make-forkexec-constructor %command2
+ #:pid-file "$PWD/$service2_pid")
+ #:stop (make-kill-destructor)
+ #:respawn? #t))
+EOF
+cat $conf
+
+rm -f "$pid"
+shepherd -I -s "$socket" -c "$conf" -l "$log" --pid="$pid" &
+
+# Wait till it's ready.
+while ! test -f "$pid" ; do sleep 0.3 ; done
+
+shepherd_pid="`cat $pid`"
+
+# start both of the services
+$herd start test
+$herd start test2
+
+# make sure "test" is started
+until $herd status test | grep started; do sleep 0.3; done
+test -f "$service_pid"
+service_pid_value="`cat $service_pid`"
+# now kill it
+kill "$service_pid_value"
+while kill -0 "$service_pid_value"; do sleep 0.3; done
+# shepherd should notice that the service has stopped within one second
+sleep 1
+$herd status test | grep stopped
+
+
+
+# make sure "test2" has started
+until $herd status test2 | grep started; do sleep 0.3; done
+test -f "$service2_pid"
+service2_pid_value="`cat $service2_pid`"
+test "`cat $PWD/$service2_started`" = "started"
+# now kill it
+rm -f "$service2_pid"
+kill $service2_pid_value
+while kill -0 "$service2_pid_value"; do sleep 0.3; done
+# shepherd should notice that the service has stopped, and restart it, within
one second
+sleep 1;
+$herd status test2 | grep started
+test "`cat $PWD/$service2_started`" = "started
+started"