pid-file.sh 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. # GNU Shepherd --- Test the #:pid-file option of 'make-forkexec-constructor'.
  2. # Copyright © 2016, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
  3. #
  4. # This file is part of the GNU Shepherd.
  5. #
  6. # The GNU Shepherd is free software; you can redistribute it and/or modify it
  7. # under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 3 of the License, or (at
  9. # your option) any later version.
  10. #
  11. # The GNU Shepherd is distributed in the hope that it will be useful, but
  12. # WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with the GNU Shepherd. If not, see <http://www.gnu.org/licenses/>.
  18. shepherd --version
  19. herd --version
  20. socket="t-socket-$$"
  21. conf="t-conf-$$"
  22. log="t-log-$$"
  23. pid="t-pid-$$"
  24. service_pid="t-service-pid-$$"
  25. herd="herd -s $socket"
  26. trap "cat $log || true; rm -f $socket $conf $service_pid $log;
  27. test -f $pid && kill \`cat $pid\` || true; rm -f $pid" EXIT
  28. cat > "$conf"<<EOF
  29. (use-modules (ice-9 match))
  30. (define %command
  31. '("$SHELL" "-c" "echo \$\$ > $PWD/$service_pid ; exec sleep 600"))
  32. (define %daemon-command
  33. ;; Emulate a daemon by forking and exiting right away.
  34. (quasiquote ("guile" "-c"
  35. ,(object->string '(when (zero? (primitive-fork))
  36. (call-with-output-file "$PWD/$service_pid"
  37. (lambda (port)
  38. (display (getpid) port)))
  39. (sleep 100))))))
  40. (define %daemon-command-successful
  41. ;; Purposefully introduce a delay between the time the PID file
  42. ;; is created and the time it actually contains a valid PID. This
  43. ;; simulates PID files not created atomically, as is the case with
  44. ;; wpa_supplicant 2.7 for instance.
  45. (quasiquote ("guile" "-c"
  46. ,(object->string '(when (zero? (primitive-fork))
  47. (call-with-output-file "$PWD/$service_pid"
  48. (lambda (port)
  49. (usleep 1500000)
  50. (display (getpid) port)))
  51. (sleep 100))))))
  52. (register-services
  53. (make <service>
  54. ;; A service that never produces its PID file, yet leaves a process
  55. ;; behind it.
  56. #:provides '(test)
  57. #:start (make-forkexec-constructor %command
  58. #:pid-file "/does-not-exist"
  59. ;; Low-end ARMv7 machines are
  60. ;; slow enough that creating
  61. ;; $service_pid could take
  62. ;; up to 4 seconds or so.
  63. #:pid-file-timeout 6)
  64. #:stop (make-kill-destructor)
  65. #:respawn? #f)
  66. (make <service>
  67. ;; Same one, but actually produces the PID file.
  68. #:provides '(test-works)
  69. #:start (make-forkexec-constructor %daemon-command-successful
  70. #:pid-file "$PWD/$service_pid"
  71. #:pid-file-timeout 6)
  72. #:stop (make-kill-destructor)
  73. #:respawn? #f)
  74. (make <service>
  75. ;; This one "daemonizes", fails to create a PID file, but leaves
  76. ;; a child process behind it.
  77. #:provides '(test-daemonizes)
  78. #:start (make-forkexec-constructor %daemon-command
  79. #:pid-file "/does-not-exist"
  80. #:pid-file-timeout 6)
  81. #:stop (make-kill-destructor)
  82. #:respawn? #f))
  83. EOF
  84. rm -f "$pid"
  85. shepherd -I -s "$socket" -c "$conf" -l "$log" --pid="$pid" &
  86. # Wait till it's ready.
  87. while ! test -f "$pid" ; do sleep 0.3 ; done
  88. shepherd_pid="`cat $pid`"
  89. # The service is expected to fail to start.
  90. if $herd start test
  91. then false; else true; fi
  92. # Make sure it is marked as stopped.
  93. $herd status test | grep stopped
  94. test -f "$service_pid"
  95. # Make sure it did not leave a process behind it.
  96. if kill -0 `cat "$service_pid"`
  97. then false; else true; fi
  98. # Now a service that "daemonizes" but fails to start.
  99. rm -f "$service_pid"
  100. if $herd start test-daemonizes
  101. then false; else true; fi
  102. $herd status test-daemonizes | grep stopped
  103. # Make sure it did not leave its child process behind it.
  104. test -f "$service_pid"
  105. if kill -0 `cat "$service_pid"`
  106. then false; else true; fi
  107. # Now start the service that works.
  108. $herd start test-works
  109. $herd status test-works | grep started
  110. test -f "$service_pid"
  111. kill -0 "`cat $service_pid`"
  112. known_pid="`$herd status test-works | grep Running \
  113. | sed -es'/.*Running value.* \([0-9]\+\)\.$/\1/g'`"
  114. test `cat $service_pid` -eq $known_pid
  115. $herd stop test-works
  116. if kill -0 `cat "$service_pid"`
  117. then false; else true; fi