As of 1.0.3, when two clients start the same one-shot service, the one that loses the race never sees the value that was produced by the ‘start’ method.
herd start one-shot & herd start one-shot Here one of the ‘herd start’ processes will wrongfully fail with “failed to start service one-shot”. Instead, it calls ‘service-running-value’ but that always returns #f because the one-shot service was stopped in the meantime. I’m referring to this bit of ‘start-service’: (match (get-message reply) (#f ;; We lost the race: SERVICE is already running. (service-running-value service)) ;<- here …) Attached is a reproducer. Ludo’.
diff --git a/tests/one-shot.sh b/tests/one-shot.sh index eeecea7..491eeae 100644 --- a/tests/one-shot.sh +++ b/tests/one-shot.sh @@ -1,5 +1,5 @@ # GNU Shepherd --- Test one-shot services. -# Copyright © 2019, 2023-2024 Ludovic Courtès <l...@gnu.org> +# Copyright © 2019, 2023-2025 Ludovic Courtès <l...@gnu.org> # # This file is part of the GNU Shepherd. # @@ -197,4 +197,35 @@ test "$(cat "$stamp")" = "third" $herd start fourth && false $herd start fourth && false +# Check the behavior of two clients competing to start the same one-shot +# service. Both should succeed. + +cat > "$conf" <<EOF +(register-services + (list (service + '(fifth) + #:one-shot? #t + #:start (lambda () + (let loop () + (unless (file-exists? "$stamp") + (sleep 0.5) + (loop))) + #t)))) +EOF + +$herd load root "$conf" + +rm -f "$stamp" + +$herd start fifth & +herd_start_pid1=$! +$herd start fifth & +herd_start_pid2=$! +until $herd status fifth | grep starting; do sleep 0.5; done +touch "$stamp" # trigger starting->running transition + +# Both 'herd start' processes should have succeeded. +wait $herd_start_pid1 +wait $herd_start_pid2 + $herd stop root