Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe86e7691d | ||
|
|
038cea416c | ||
|
|
e2bd550d13 | ||
|
|
ac49814607 | ||
|
|
09fc8fe09c | ||
|
|
3a2774732a | ||
|
|
dec0722c30 | ||
|
|
949daeb68b | ||
|
|
fbab2affd2 | ||
|
|
2824905935 | ||
|
|
60eadd5fa2 | ||
|
|
2a203b9b6e | ||
|
|
a769ea1b92 | ||
|
|
6f564b59cc | ||
|
|
e312e56997 | ||
|
|
2f60a959b4 | ||
|
|
25b45a5a23 | ||
|
|
4651b8c7e9 | ||
|
|
50608b54ed | ||
|
|
b0a077a35f | ||
|
|
6a5ca2ab36 | ||
|
|
2b0345165e | ||
|
|
8885580986 | ||
|
|
6d7713a758 | ||
|
|
457f928e79 | ||
|
|
a71a461e45 | ||
|
|
a09b8af3f9 | ||
|
|
382efdbfcb | ||
|
|
17b5cc78d3 | ||
|
|
36a0ab9054 | ||
|
|
27c2bd997d | ||
|
|
d7938f54f2 | ||
|
|
cfbe9c2ede |
500
ChangeLog
500
ChangeLog
@@ -1,3 +1,261 @@
|
||||
commit 038cea416c0a4cda83872733ab660cf0bb2b5eaf
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
ignore sigchld when shutting down the supervised process
|
||||
|
||||
We need to do this to skip the zombie state for the child process since
|
||||
we are not easily able to wait() for it.
|
||||
|
||||
commit e2bd550d13d23ce132650d7e3dc36dc512bf048e
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
typo fix
|
||||
|
||||
commit ac498146071636a3fbda4fb48ff64102c244415d
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
typo fix
|
||||
|
||||
commit 09fc8fe09c01a347666de66fb11e759de371a873
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
supervise-daemon: code cleanup
|
||||
|
||||
Clean up the process for killing an active supervisor when stopping.
|
||||
|
||||
commit 3a2774732aa629083bc6395c5c7a8a3040e64b60
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
initialize the stop schedule
|
||||
|
||||
commit dec0722c30e41480d300549a69d3672c38e0c15d
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
rc-schedules.c: pass the correct pid to rc_find_pids
|
||||
|
||||
This is for #163.
|
||||
|
||||
commit 949daeb68b2a39fa1e64f2eb3fa72579f98df09e
|
||||
Author: Jason Zaman <jason@perfinion.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
selinux: fix const qualifier warning
|
||||
|
||||
rc-selinux.c: In function ‘selinux_setup’:
|
||||
rc-selinux.c:361:9: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
|
||||
curr_t = context_type_get(curr_con);
|
||||
^
|
||||
|
||||
commit fbab2affd2d5309ed4b5416e0e239902d77b4232
|
||||
Author: Jason Zaman <jason@perfinion.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
selinux: use openrc contexts path to get contexts
|
||||
|
||||
The minimum requirement for libselinux is now >=2.6
|
||||
The refpolicy and the gentoo policy contain the
|
||||
contexts since version 2.20170204-r4
|
||||
|
||||
commit 28249059356d8b611a46c5493574abe9805ab48b
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
version 0.31.2
|
||||
|
||||
commit 60eadd5fa2ba2675caab4f977b8627bc07e39e8e
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Update ChangeLog
|
||||
|
||||
commit 2a203b9b6e91e4ed140750eb9223012035870864
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
sysfs: fix cgroup hybrid mode
|
||||
|
||||
In hybrid mode, we should not try to mount cgroup2 if it is not
|
||||
available in the kernel.
|
||||
|
||||
This fixes #164.
|
||||
|
||||
commit a769ea1b92f47254edf11458d2c8b79d3819e0e6
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
cgroup2_find_path: use legacy mode if cgroup2 is not in the kernel
|
||||
|
||||
This is related to #164.
|
||||
|
||||
commit 6f564b59cc15e688b2fa0758fa9797632e0751d7
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
version 0.31.1
|
||||
|
||||
commit e312e569970c74cf52e255da67034391b68dafac
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Update ChangeLog
|
||||
|
||||
commit 2f60a959b442866b0e879d83f2732c4fa3ed3f7d
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
update news file
|
||||
|
||||
commit 25b45a5a239318fb57c405c3fe64e53b0738ad68
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
cgroup_cleanup: try to remove the cgroup version 2 cgroup
|
||||
|
||||
If we were able to kill all the processes in the cgroup, it should be
|
||||
removed.
|
||||
|
||||
commit 4651b8c7e9e2ef9c1ea1fb8d174d1ca4693627af
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
rc-cgroup.sh: cgroup_cleanup fix error handling
|
||||
|
||||
cgroup_cleanup should warn if it is unable to clean up all processes in
|
||||
the control group, but it will always return success.
|
||||
|
||||
commit 50608b54ed98acb54fec5fe3323909ea684d3af9
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
rc-cgroup.sh: fix signal names
|
||||
|
||||
The "SIG" prefix on signal names passed to kill -s isn't portable.
|
||||
|
||||
commit b0a077a35f85e266fdb82a245dcbda18664a8567
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
add quiet switch to do_stop in src-schedules.c
|
||||
|
||||
This allows supervise-daemon to run this code without attempting to
|
||||
print some status messages used by start-stop-daemon.
|
||||
|
||||
commit 6a5ca2ab368d0a85f51bb559672dba2e3ffcc6be
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
make the procedure for killing child processes of services configurable
|
||||
|
||||
commit 2b0345165e5af57ca61a4000c3671bbe6d677cf9
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Make cgroup_cleanup send only one sigterm and sigkill
|
||||
|
||||
Instead of looping and sending multiple signals to child processes in
|
||||
cgroup_cleanup, we send sigterm followed by sleeping one second then
|
||||
sigkill.
|
||||
|
||||
This brings us more in line with systemd's "control group" killmode
|
||||
setting.
|
||||
|
||||
Also, this commit includes several shellcheck cleanups.
|
||||
|
||||
commit 8885580986ab8adc951fe32b9323c8b16130fb4f
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
rc-cgroup.sh: move cgroup_cleanup to the end of the file
|
||||
|
||||
commit 6d7713a758b7e78f05e6a3cc101f862d28d778ab
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
guide.md: clarify cgroups documentation
|
||||
|
||||
Update the documentation to reflect cgroups version 2 support.
|
||||
Also, add a section on dealing with orphaned service processes.
|
||||
|
||||
This fixes #94.
|
||||
|
||||
commit 457f928e793cb1f6ef254935ad07f58b8762c72f
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
add support for control groups version 2
|
||||
|
||||
This is for #94.
|
||||
|
||||
commit a71a461e452a98554346c47411e9c9012023c201
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
version 0.31
|
||||
|
||||
commit a09b8af3f98c0700a9b838b7f3683ee58eecc912
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Update ChangeLog
|
||||
|
||||
commit 382efdbfcb99703d03211efacd800c9575e64230
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
add quiet parameter to run_stop_schedule
|
||||
|
||||
commit 17b5cc78d35dc5fe4904e5951715c3e0d07d6343
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
add retry option to supervise-daemon
|
||||
|
||||
The --retry option for supervise-daemon defines how the supervisor will
|
||||
attempt to stop the child process it is monitoring. It is defined when
|
||||
the supervisor is started since stopping the supervisor just sends a
|
||||
signal to the active supervisor.
|
||||
|
||||
This fixes #160.
|
||||
|
||||
commit 36a0ab9054512ade413226fb8e8b28060045e9a4
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
make run_stop_schedule accept a pid instead of a pid file
|
||||
|
||||
commit 27c2bd997d5173aa30844a16bc22dc8caab09f8c
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
version 0.30
|
||||
|
||||
commit d7938f54f29193251e083ad35a7d464949829096
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
start-stop-daemon: move --retry processing code to a shared module
|
||||
|
||||
This was part of start-stop-daemon; however, it needs to be shared in
|
||||
order to be used by supervise-daemon.
|
||||
|
||||
commit cfbe9c2ede24dac530ef58e5c35bd57f22a788a3
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
move get_pid function to a shared file
|
||||
|
||||
commit df28002b728b033c00c2da64dedf2bcd4ab5e11b
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Update ChangeLog
|
||||
|
||||
commit 66ed8082d0c865a0b4f4cc436cf9e13351e3d6fe
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
@@ -1270,245 +1528,3 @@ Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
now have a request to enable it.
|
||||
|
||||
This fixes #24.
|
||||
|
||||
commit c146b966913ae80652e3be925d3aba60ed82f14d
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Add command_progress variable
|
||||
|
||||
If this is set to yes, 1, true, or on, start-stop-daemon will display a
|
||||
progress meter while waiting for a daemon to stop.
|
||||
|
||||
commit 6cabaf274defa11773094a2c85b3d0a9f0bd9b08
|
||||
Author: Doug Freed <dwfreed@mtu.edu>
|
||||
Commit: Doug Freed <dwfreed@mtu.edu>
|
||||
|
||||
rc-misc: allow EINFO_VERBOSE through too
|
||||
|
||||
commit 1edb5f6fd9c4827e5d4ed5c854bc322ba8a7df73
|
||||
Author: Doug Freed <dwfreed@mtu.edu>
|
||||
Commit: Doug Freed <dwfreed@mtu.edu>
|
||||
|
||||
rc-misc: Allow EINFO_COLOR through env_filter()
|
||||
|
||||
This allows rc-service -C <service> <action> to properly not print color
|
||||
messages.
|
||||
|
||||
Fixes #93
|
||||
|
||||
commit c4d7e02abd7008b8e8ad16f62c2abbb60fab252b
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Fix permission checks for cgroups
|
||||
|
||||
This is needed because containers may give read access to cgroups but
|
||||
not allow the settings to be changed.
|
||||
|
||||
commit a4e0d675e13f07bf880da10a4d602983a556264d
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
man/openrc-run.8: update variable documentation
|
||||
|
||||
- document command_args_background and command_user.r
|
||||
- clarify documentation for command_background
|
||||
|
||||
This fixes #78.
|
||||
|
||||
commit 8a8032478a755f6e2ceaebc5425e61c6817df936
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Make use of name vs RC_SVCNAME consistent in supervisor scripts
|
||||
|
||||
This fixes #79.
|
||||
|
||||
commit ac53c9a658589456c678b6bfe674a66a3845e564
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
sh/init.sh: fix the test for cache restoration
|
||||
|
||||
This fixes the test for cache restoration since we are no longer caching
|
||||
the dependency tree.
|
||||
|
||||
commit b02ff466fa75cc4b5bcfaff3f2989cc65c823f43
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
savecache: stop saving the dependency tree
|
||||
|
||||
This fixes #85.
|
||||
|
||||
commit 6bd0f2d096f149906061a4ac7b66b7e85516784a
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
init.d/procfs: typo fix
|
||||
|
||||
commit 63f8ae466f046dcdbb0ba13ef96e63eeec86e6e6
|
||||
Author: frickler01 <frickler01@users.noreply.github.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Format code blocks and variable/path notations
|
||||
|
||||
Add markdown backticks for commands, variable names and path as well
|
||||
as code blocks for better readability.
|
||||
|
||||
This fixes #97.
|
||||
|
||||
commit 841b883825ddf9982a673b3964757f6df25acd46
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
hwclock: fix module load warning
|
||||
|
||||
commit ba10793b0b85b11fae04e6526716c6f7976afde1
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
init.d/procfs: fix binfmt_misc module load warning
|
||||
|
||||
This reworks the logic so that the warning about configuring the
|
||||
binfmt_misc module is only displayed if the module actually has to be
|
||||
loaded.
|
||||
|
||||
commit d4d559323819c8a5279bf197d8d3ff80f1e28cdc
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
sh/openrc-run.sh: read global configuration settings first
|
||||
|
||||
X-Gentoo-Bug: 503134
|
||||
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=503134
|
||||
|
||||
commit d5db5489be135ae9295e378e789b4b7b13367fdd
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
init.d/swap: do not unmount all tmpfs file systems
|
||||
|
||||
X-Gentoo-Bug: 568162
|
||||
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=568162
|
||||
|
||||
commit d06db93d5954460668d09cf6ef2fc401ee9d981c
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
remove swapfiles service
|
||||
|
||||
The swapfiles service was basically a copy of the swap service, so this
|
||||
commit consolidates the functionality into the swap service.
|
||||
|
||||
X-Funtoo-Bug-URL: https://bugs.funtoo.org/browse/FL-2523
|
||||
X-Gentoo-Bug: 568162
|
||||
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=568162
|
||||
|
||||
commit 8c14d0c476e06fff7598c526e26b6a13d53a4600
|
||||
Author: Martin Väth <martin@mvath.de>
|
||||
Commit: Martin Väth <martin@mvath.de>
|
||||
|
||||
Fix typo in RC_UNAME check of modules-load
|
||||
|
||||
The $RC_UNAME "Linux" had been misspelled as "linux".
|
||||
As a consequence, entries in e.g. /etc/modules-load.d failed to
|
||||
load any module succesfully under Linux(!)
|
||||
|
||||
commit 04debf6f25b3748a101b61cb85f78617dbe5be6e
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
another news typo fix
|
||||
|
||||
commit c289774b00d0d7dc38fdc1f0f623569bd184a4b1
|
||||
Author: Doug Freed <dwfreed@mtu.edu>
|
||||
Commit: Doug Freed <dwfreed@mtu.edu>
|
||||
|
||||
modules-load: handle comments better
|
||||
|
||||
This handles comments without a trailing space after the comment
|
||||
character.
|
||||
|
||||
Reported-By: josef64
|
||||
|
||||
commit 9dd8ee330d8a4449c937bc95fc8393a55913c8d1
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
typo fix
|
||||
|
||||
commit 5d5856c193768d24f11d5f0533e48c39526aef5c
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Update news file
|
||||
|
||||
Add information on modules-load service and more explanation about
|
||||
dealing with the rc -> openrc and runscript -> openrc-run transitions.
|
||||
|
||||
commit 686e172207ac9e23560da18a6f877be777ded935
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
init.d: add modules-load to ignore patterns
|
||||
|
||||
commit fef6268f8d03e3ab3e2564cbf3634d0db2bcd99e
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
modules-load.d: cleanups
|
||||
|
||||
Move list of directories to a local variable and create the fn variable
|
||||
to use for an individual file name rather than using path.
|
||||
|
||||
commit 556dbff99d53cdcc00e6b1ec67e1679f72b6f284
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Add modules-load.d support
|
||||
|
||||
commit 69ac78d76a31d843c004717eb6aa6a77bb4c9a8e
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
openrc-run: make runscript warning respect quiet option
|
||||
|
||||
X-Gentoo-Bug: 591414
|
||||
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=591414
|
||||
|
||||
commit 4018dfc8de4818101c336ff8bcf0f4762b318c6a
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
init.d/hostname: do not use localhost as a default hostname
|
||||
|
||||
This allows the operating system default hostname to be used if no
|
||||
hostname is configured.
|
||||
|
||||
commit 353bb9bc9a0ab3c6650d72d2ceb14c990762a2a0
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
init.d/hostname: add support for /etc/hostname
|
||||
|
||||
commit 73cdf10f1f513be7b5dec4f1cc91e0c68cda689b
|
||||
Author: William Hubbs <w.d.hubbs@gmail.com>
|
||||
Commit: William Hubbs <w.d.hubbs@gmail.com>
|
||||
|
||||
Deprecate automatic loading of modules
|
||||
|
||||
In the hwclock, procfs and sysfs service scripts, we automatically
|
||||
attempt to load the kernel modules we need before we take any action. We
|
||||
shouldn't do this, because there are systems which do not use kernel
|
||||
modules and do not have the kmod package installed.
|
||||
|
||||
With this change, we continue to load the modules ourselves, but we warn
|
||||
the admin that they need to be added to /etc/conf.d/modules or built
|
||||
into the kernel.
|
||||
|
||||
In the future, this automatic loading will be dropped.
|
||||
|
||||
X-Gentoo-Bug: 342313
|
||||
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=342313
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
NAME= openrc
|
||||
VERSION= 0.29
|
||||
VERSION= 0.31.2
|
||||
PKG= ${NAME}-${VERSION}
|
||||
|
||||
6
NEWS.md
6
NEWS.md
@@ -3,6 +3,12 @@
|
||||
This file will contain a list of notable changes for each release. Note
|
||||
the information in this file is in reverse order.
|
||||
|
||||
## OpenRC 0.31
|
||||
|
||||
This version adds support for Control Groups version 2, which is
|
||||
considered stable as of Linux-4.13. Please see /etc/rc.conf for
|
||||
documentation on how to configure control groups.
|
||||
|
||||
## OpenRC-0.28
|
||||
|
||||
This version mounts efivars read only due to concerns about changes in
|
||||
|
||||
74
etc/rc.conf
74
etc/rc.conf
@@ -191,13 +191,43 @@ rc_tty_number=12
|
||||
##############################################################################
|
||||
# LINUX CGROUPS RESOURCE MANAGEMENT
|
||||
|
||||
# If you have cgroups turned on in your kernel, this switch controls
|
||||
# whether or not a group for each controller is mounted under
|
||||
# /sys/fs/cgroup.
|
||||
# None of the other options in this section work if this is set to "NO".
|
||||
# This sets the mode used to mount cgroups.
|
||||
# "hybrid" mounts cgroups version 2 on /sys/fs/cgroup/unified and
|
||||
# cgroups version 1 on /sys/fs/cgroup.
|
||||
# "legacy" mounts cgroups version 1 on /sys/fs/cgroup
|
||||
# "unified" mounts cgroups version 2 on /sys/fs/cgroup
|
||||
#rc_cgroup_mode="hybrid"
|
||||
|
||||
# This is a list of controllers which should be enabled for cgroups version 2.
|
||||
# If hybrid mode is being used, controllers listed here will not be
|
||||
# available for cgroups version 1.
|
||||
# This is a global setting.
|
||||
#rc_cgroup_controllers=""
|
||||
|
||||
# This variable contains the cgroups version 2 settings for your services.
|
||||
# If this is set in this file, the settings will apply to all services.
|
||||
# If you want different settings for each service, place the settings in
|
||||
# /etc/conf.d/foo for service foo.
|
||||
# The format is to specify the setting and value followed by a newline.
|
||||
# Multiple settings and values can be specified.
|
||||
# For example, you would use this to set the maximum memory and maximum
|
||||
# number of pids for a service.
|
||||
#rc_cgroup_settings="
|
||||
#memory.max 10485760
|
||||
#pids.max max
|
||||
#"
|
||||
#
|
||||
# For more information about the adjustments that can be made with
|
||||
# cgroups version 2, see Documentation/cgroups-v2.txt in the linux kernel
|
||||
# source tree.
|
||||
#rc_cgroup_settings=""
|
||||
|
||||
# This switch controls whether or not cgroups version 1 controllers are
|
||||
# individually mounted under
|
||||
# /sys/fs/cgroup in hybrid or legacy mode.
|
||||
#rc_controller_cgroups="YES"
|
||||
|
||||
# The following settings allow you to set up values for the cgroup
|
||||
# The following settings allow you to set up values for the cgroups version 1
|
||||
# controllers for your services.
|
||||
# They can be set in this file;, however, if you do this, the settings
|
||||
# will apply to all of your services.
|
||||
@@ -211,8 +241,9 @@ rc_tty_number=12
|
||||
# cpu.shares 512
|
||||
# "
|
||||
#
|
||||
#For more information about the adjustments that can be made with
|
||||
#cgroups, see Documentation/cgroups/* in the linux kernel source tree.
|
||||
# For more information about the adjustments that can be made with
|
||||
# cgroups version 1, see Documentation/cgroups-v1/* in the linux kernel
|
||||
# source tree.
|
||||
|
||||
# Set the blkio controller settings for this service.
|
||||
#rc_cgroup_blkio=""
|
||||
@@ -246,10 +277,33 @@ rc_tty_number=12
|
||||
|
||||
# Set this to YES if you want all of the processes in a service's cgroup
|
||||
# killed when the service is stopped or restarted.
|
||||
# This should not be set globally because it kills all of the service's
|
||||
# child processes, and most of the time this is undesirable. Please set
|
||||
# it in /etc/conf.d/<service>.
|
||||
# Be aware that setting this to yes means all of a service's
|
||||
# child processes will be killed. Keep this in mind if you set this to
|
||||
# yes here instead of for the individual services in
|
||||
# /etc/conf.d/<service>.
|
||||
# To perform this cleanup manually for a stopped service, you can
|
||||
# execute cgroup_cleanup with /etc/init.d/<service> cgroup_cleanup or
|
||||
# rc-service <service> cgroup_cleanup.
|
||||
# The process followed in this cleanup is the following:
|
||||
# 1. send stopsig (sigterm if it isn't set) to all processes left in the
|
||||
# cgroup immediately followed by sigcont.
|
||||
# 2. Send sighup to all processes in the cgroup if rc_send_sighup is
|
||||
# yes.
|
||||
# 3. delay for rc_timeout_stopsec seconds.
|
||||
# 4. send sigkill to all processes in the cgroup unless disabled by
|
||||
# setting rc_send_sigkill to no.
|
||||
# rc_cgroup_cleanup="NO"
|
||||
|
||||
# If this is yes, we will send sighup to the processes in the cgroup
|
||||
# immediately after stopsig and sigcont.
|
||||
#rc_send_sighup="NO"
|
||||
|
||||
# This is the amount of time in seconds that we delay after sending sigcont
|
||||
# and optionally sighup, before we optionally send sigkill to all
|
||||
# processes in the # cgroup.
|
||||
# The default is 90 seconds.
|
||||
#rc_timeout_stopsec="90"
|
||||
|
||||
# If this is set to no, we do not send sigkill to all processes in the
|
||||
# cgroup.
|
||||
#rc_send_sigkill="YES"
|
||||
|
||||
37
guide.md
37
guide.md
@@ -241,17 +241,36 @@ messages to a file), and a few others.
|
||||
|
||||
# ulimit and CGroups
|
||||
|
||||
Setting `ulimit` and `nice` values per service can be done through the `rc_ulimit`
|
||||
variable.
|
||||
Setting `ulimit` and `nice` values per service can be done through the
|
||||
`rc_ulimit` variable.
|
||||
|
||||
Under Linux, OpenRC can optionally use CGroups for process management.
|
||||
By default each service script's processes are migrated to their own CGroup.
|
||||
Under Linux, OpenRC can use cgroups for process management as well. Once
|
||||
the kernel is configured appropriately, the `rc_cgroup_mode` setting in
|
||||
/etc/rc.conf should be used to control whether cgroups version one,,
|
||||
two, or both are used. The default is to use both if they are available.
|
||||
|
||||
By changing certain settings in the service's `conf.d` file limits can be
|
||||
enforced per service. These settings are documented in detail in the
|
||||
default /etc/rc.conf under `LINUX CGROUPS RESOURCE MANAGEMENT`.
|
||||
|
||||
# Dealing with Orphaned Processes
|
||||
|
||||
It is possible to get into a state where there are orphaned processes
|
||||
running which were part of a service. For example, if you are monitoring
|
||||
a service with supervise-daemon and supervise-daemon dies for an unknown
|
||||
reason. The way to deal with this will be different for each system.
|
||||
|
||||
On Linux systems with cgroups enabled, the cgroup_cleanup command is
|
||||
added to all services. You can run it manually, when the service is
|
||||
stopped, by using:
|
||||
|
||||
```
|
||||
# rc-service someservice cgroup_cleanup
|
||||
```
|
||||
|
||||
The `rc_cgroup_cleanup` setting can be changed to yes to make this
|
||||
happen automatically when the service is stopped.
|
||||
|
||||
By changing certain values in the `conf.d` file limits can be enforced per
|
||||
service. It is easy to find orphan processes of a service that persist after
|
||||
`stop()`, but by default these will NOT be terminated.
|
||||
To change this add `rc_cgroup_cleanup="yes"` in the `conf.d` files for services
|
||||
where you desire this functionality.
|
||||
|
||||
# Caching
|
||||
|
||||
|
||||
109
init.d/sysfs.in
109
init.d/sysfs.in
@@ -107,20 +107,16 @@ mount_misc()
|
||||
fi
|
||||
}
|
||||
|
||||
mount_cgroups()
|
||||
cgroup1_base()
|
||||
{
|
||||
# set up kernel support for cgroups
|
||||
if [ -d /sys/fs/cgroup ] && ! mountinfo -q /sys/fs/cgroup; then
|
||||
if grep -qs cgroup /proc/filesystems; then
|
||||
ebegin "Mounting cgroup filesystem"
|
||||
local opts="${sysfs_opts},mode=755,size=${rc_cgroupsize:-10m}"
|
||||
mount -n -t tmpfs -o ${opts} cgroup_root /sys/fs/cgroup
|
||||
eend $?
|
||||
fi
|
||||
grep -qw cgroup /proc/filesystems || return 0
|
||||
if ! mountinfo -q /sys/fs/cgroup; then
|
||||
ebegin "Mounting cgroup filesystem"
|
||||
local opts="${sysfs_opts},mode=755,size=${rc_cgroupsize:-10m}"
|
||||
mount -n -t tmpfs -o "${opts}" cgroup_root /sys/fs/cgroup
|
||||
eend $?
|
||||
fi
|
||||
|
||||
mountinfo -q /sys/fs/cgroup || return 0
|
||||
|
||||
if ! mountinfo -q /sys/fs/cgroup/openrc; then
|
||||
local agent="@LIBEXECDIR@/sh/cgroup-release-agent.sh"
|
||||
mkdir /sys/fs/cgroup/openrc
|
||||
@@ -129,17 +125,96 @@ mount_cgroups()
|
||||
openrc /sys/fs/cgroup/openrc
|
||||
printf 1 > /sys/fs/cgroup/openrc/notify_on_release
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
yesno ${rc_controller_cgroups:-YES} && [ -e /proc/cgroups ] || return 0
|
||||
while read name hier groups enabled rest; do
|
||||
cgroup1_controllers()
|
||||
{
|
||||
yesno "${rc_controller_cgroups:-YES}" && [ -e /proc/cgroups ] || return 0
|
||||
while read -r name _ _ enabled rest; do
|
||||
case "${enabled}" in
|
||||
1) mountinfo -q /sys/fs/cgroup/${name} && continue
|
||||
mkdir /sys/fs/cgroup/${name}
|
||||
mount -n -t cgroup -o ${sysfs_opts},${name} \
|
||||
${name} /sys/fs/cgroup/${name}
|
||||
1) mountinfo -q "/sys/fs/cgroup/${name}" && continue
|
||||
local x
|
||||
for x in $rc_cgroup_controllers; do
|
||||
[ "${name}" = "blkio" ] && [ "${x}" = "io" ] &&
|
||||
continue 2
|
||||
[ "${name}" = "${x}" ] &&
|
||||
continue 2
|
||||
done
|
||||
mkdir "/sys/fs/cgroup/${name}"
|
||||
mount -n -t cgroup -o "${sysfs_opts},${name}" \
|
||||
"${name}" "/sys/fs/cgroup/${name}"
|
||||
;;
|
||||
esac
|
||||
done < /proc/cgroups
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroup2_base()
|
||||
{
|
||||
local base
|
||||
base="$(cgroup2_find_path)"
|
||||
mkdir -p "${base}"
|
||||
mount -t cgroup2 none -o "${sysfs_opts},nsdelegate" "${base}" 2> /dev/null ||
|
||||
mount -t cgroup2 none -o "${sysfs_opts}" "${base}"
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroup2_controllers()
|
||||
{
|
||||
local active cgroup_path x y
|
||||
cgroup_path="$(cgroup2_find_path)"
|
||||
[ -z "${cgroup_path}" ] && return 0
|
||||
[ -e "${cgroup_path}/cgroup.controllers" ] &&
|
||||
read -r active < "${cgroup_path}/cgroup.controllers"
|
||||
for x in ${rc_cgroup_controllers}; do
|
||||
for y in ${active}; do
|
||||
[ "$x" = "$y" ] &&
|
||||
[ -e "${cgroup_path}/cgroup.subtree_control" ]&&
|
||||
echo "+${x}" > "${cgroup_path}/cgroup.subtree_control"
|
||||
done
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroups_hybrid()
|
||||
{
|
||||
grep -qw cgroup /proc/filesystems || return 0
|
||||
cgroup1_base
|
||||
if grep -qw cgroup2 /proc/filesystems; then
|
||||
cgroup2_base
|
||||
cgroup2_controllers
|
||||
fi
|
||||
cgroup1_controllers
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroups_legacy()
|
||||
{
|
||||
grep -qw cgroup /proc/filesystems || return 0
|
||||
cgroup1_base
|
||||
cgroup1_controllers
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroups_unified()
|
||||
{
|
||||
cgroup2_base
|
||||
cgroup2_controllers
|
||||
return 0
|
||||
}
|
||||
|
||||
mount_cgroups()
|
||||
{
|
||||
# set up kernel support for cgroups
|
||||
if [ -d /sys/fs/cgroup ]; then
|
||||
case "${rc_cgroup_mode:-hybrid}" in
|
||||
hybrid) cgroups_hybrid ;;
|
||||
legacy) cgroups_legacy ;;
|
||||
unified) cgroups_unified ;;
|
||||
esac
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
restorecon_sys()
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
.Ar pidfile
|
||||
.Fl P , -respawn-period
|
||||
.Ar seconds
|
||||
.Fl R , -retry
|
||||
.Ar arg
|
||||
.Fl r , -chroot
|
||||
.Ar chrootpath
|
||||
.Fl u , -user
|
||||
@@ -115,6 +117,9 @@ Modifies the scheduling priority of the daemon.
|
||||
.It Fl P , -respawn-period Ar seconds
|
||||
Sets the length of a respawn period. The default is 10 seconds. See the
|
||||
description of --respawn-max for more information.
|
||||
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
|
||||
The retry specification can be either a timeout in seconds or multiple
|
||||
signal/timeout pairs (like SIGTERM/5).
|
||||
.It Fl r , -chroot Ar path
|
||||
chroot to this directory before starting the daemon. All other paths, such
|
||||
as the path to the daemon, chdir and pidfile, should be relative to the chroot.
|
||||
|
||||
@@ -258,8 +258,7 @@ for _cmd; do
|
||||
[ -n "${rc_ulimit:-$RC_ULIMIT}" ] && \
|
||||
ulimit ${rc_ulimit:-$RC_ULIMIT}
|
||||
# Apply cgroups settings if defined
|
||||
if [ "$(command -v cgroup_add_service)" = \
|
||||
"cgroup_add_service" ]
|
||||
if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ]
|
||||
then
|
||||
if [ -d /sys/fs/cgroup -a ! -w /sys/fs/cgroup ]; then
|
||||
eerror "No permission to apply cgroup settings"
|
||||
@@ -268,9 +267,11 @@ for _cmd; do
|
||||
cgroup_add_service /sys/fs/cgroup/openrc
|
||||
cgroup_add_service /sys/fs/cgroup/systemd/system
|
||||
fi
|
||||
[ "$(command -v cgroup_set_limits)" = \
|
||||
"cgroup_set_limits" ] && \
|
||||
cgroup_set_limits
|
||||
[ "$(command -v cgroup_set_limits)" = "cgroup_set_limits" ] &&
|
||||
cgroup_set_limits
|
||||
[ "$(command -v cgroup2_set_limits)" = "cgroup2_set_limits" ] &&
|
||||
[ "$_cmd" = start ] &&
|
||||
cgroup2_set_limits
|
||||
break
|
||||
fi
|
||||
done
|
||||
@@ -364,10 +365,14 @@ while [ -n "$1" ]; do
|
||||
then
|
||||
"$1"_post || exit $?
|
||||
fi
|
||||
[ "$(command -v cgroup_cleanup)" = "cgroup_cleanup" -a \
|
||||
"$1" = "stop" ] && \
|
||||
yesno "${rc_cgroup_cleanup}" && \
|
||||
[ "$(command -v cgroup_cleanup)" = "cgroup_cleanup" ] &&
|
||||
[ "$1" = "stop" ] &&
|
||||
yesno "${rc_cgroup_cleanup}" && \
|
||||
cgroup_cleanup
|
||||
if [ "$(command -v cgroup2_remove)" = "cgroup2_remove" ]; then
|
||||
[ "$1" = stop ] || [ -z "${command}" ] &&
|
||||
cgroup2_remove
|
||||
fi
|
||||
shift
|
||||
continue 2
|
||||
else
|
||||
|
||||
@@ -14,46 +14,56 @@ description_cgroup_cleanup="Kill all processes in the cgroup"
|
||||
|
||||
cgroup_find_path()
|
||||
{
|
||||
local OIFS n name dir result
|
||||
local OIFS name dir result
|
||||
[ -n "$1" ] || return 0
|
||||
OIFS="$IFS"
|
||||
IFS=":"
|
||||
while read n name dir; do
|
||||
while read -r _ name dir; do
|
||||
[ "$name" = "$1" ] && result="$dir"
|
||||
done < /proc/1/cgroup
|
||||
IFS="$OIFS"
|
||||
echo $result
|
||||
printf "%s" "${result}"
|
||||
}
|
||||
|
||||
cgroup_get_pids()
|
||||
{
|
||||
local p
|
||||
pids=
|
||||
while read p; do
|
||||
[ $p -eq $$ ] || pids="${pids} ${p}"
|
||||
done < /sys/fs/cgroup/openrc/${RC_SVCNAME}/tasks
|
||||
[ -n "$pids" ]
|
||||
local cgroup_procs p pids
|
||||
cgroup_procs="$(cgroup2_find_path)"
|
||||
[ -n "${cgroup_procs}" ] &&
|
||||
cgroup_procs="${cgroup_procs}/${RC_SVCNAME}/cgroup.procs" ||
|
||||
cgroup_procs="/sys/fs/cgroup/openrc/${RC_SVCNAME}/tasks"
|
||||
[ -f "${cgroup_procs}" ] || return 0
|
||||
while read -r p; do
|
||||
[ "$p" -eq $$ ] || pids="${pids} ${p}"
|
||||
done < "${cgroup_procs}"
|
||||
printf "%s" "${pids}"
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroup_running()
|
||||
{
|
||||
[ -d "/sys/fs/cgroup/openrc/${RC_SVCNAME}" ]
|
||||
[ -d "/sys/fs/cgroup/unified/${RC_SVCNAME}" ] ||
|
||||
[ -d "/sys/fs/cgroup/${RC_SVCNAME}" ] ||
|
||||
[ -d "/sys/fs/cgroup/openrc/${RC_SVCNAME}" ]
|
||||
}
|
||||
|
||||
cgroup_set_values()
|
||||
{
|
||||
[ -n "$1" -a -n "$2" -a -d "/sys/fs/cgroup/$1" ] || return 0
|
||||
[ -n "$1" ] && [ -n "$2" ] && [ -d "/sys/fs/cgroup/$1" ] || return 0
|
||||
|
||||
local controller="$1" h=$(cgroup_find_path "$1")
|
||||
local controller h
|
||||
controller="$1"
|
||||
h=$(cgroup_find_path "$1")
|
||||
cgroup="/sys/fs/cgroup/${1}${h}openrc_${RC_SVCNAME}"
|
||||
[ -d "$cgroup" ] || mkdir -p "$cgroup"
|
||||
|
||||
set -- $2
|
||||
local name val
|
||||
while [ -n "$1" -a "$controller" != "cpuacct" ]; do
|
||||
while [ -n "$1" ] && [ "$controller" != "cpuacct" ]; do
|
||||
case "$1" in
|
||||
$controller.*)
|
||||
if [ -n "$name" -a -w "$cgroup/$name" -a -n "$val" ]; then
|
||||
if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] &&
|
||||
[ -n "${val}" ]; then
|
||||
veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
|
||||
printf "%s" "$val" > "$cgroup/$name"
|
||||
fi
|
||||
@@ -68,7 +78,7 @@ cgroup_set_values()
|
||||
esac
|
||||
shift
|
||||
done
|
||||
if [ -n "$name" -a -w "$cgroup/$name" -a -n "$val" ]; then
|
||||
if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] && [ -n "${val}" ]; then
|
||||
veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
|
||||
printf "%s" "$val" > "$cgroup/$name"
|
||||
fi
|
||||
@@ -134,21 +144,78 @@ cgroup_set_limits()
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroup2_find_path()
|
||||
{
|
||||
if grep -qw cgroup2 /proc/filesystems; then
|
||||
case "${rc_cgroup_mode:-hybrid}" in
|
||||
hybrid) printf "/sys/fs/cgroup/unified" ;;
|
||||
unified) printf "/sys/fs/cgroup" ;;
|
||||
esac
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroup2_remove()
|
||||
{
|
||||
local cgroup_path rc_cgroup_path
|
||||
cgroup_path="$(cgroup2_find_path)"
|
||||
[ -z "${cgroup_path}" ] && return 0
|
||||
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
|
||||
[ ! -d "${rc_cgroup_path}" ] ||
|
||||
[ ! -e "${rc_cgroup_path}"/cgroup.events ] &&
|
||||
return 0
|
||||
grep -qx "$$" "${rc_cgroup_path}/cgroup.procs" &&
|
||||
echo 0 > "${cgroup_path}/cgroup.procs"
|
||||
local key populated vvalue
|
||||
while read -r key value; do
|
||||
case "${key}" in
|
||||
populated) populated=${value} ;;
|
||||
*) ;;
|
||||
esac
|
||||
done < "${rc_cgroup_path}/cgroup.events"
|
||||
[ "${populated}" = 1 ] && return 0
|
||||
rmdir "${rc_cgroup_path}"
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroup2_set_limits()
|
||||
{
|
||||
local cgroup_path
|
||||
cgroup_path="$(cgroup2_find_path)"
|
||||
[ -d "${cgroup_path}" ] || return 0
|
||||
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
|
||||
local OIFS="$IFS"
|
||||
IFS="
|
||||
"
|
||||
[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
|
||||
echo 0 > "${rc_cgroup_path}/cgroup.procs"
|
||||
echo "${rc_cgroup_settings}" | while IFS="$OIFS" read -r key value; do
|
||||
[ -z "${key}" ] || [ -z "${value}" ] && continue
|
||||
[ ! -e "${rc_cgroup_path}/${key}" ] && continue
|
||||
veinfo "${RC_SVCNAME}: cgroups: ${key} ${value}"
|
||||
echo "${value}" > "${rc_cgroup_path}/${key}"
|
||||
done
|
||||
IFS="$OIFS"
|
||||
return 0
|
||||
}
|
||||
|
||||
cgroup_cleanup()
|
||||
{
|
||||
cgroup_running || return 0
|
||||
ebegin "starting cgroups cleanup"
|
||||
for sig in TERM QUIT INT; do
|
||||
cgroup_get_pids || { eend 0 "finished" ; return 0 ; }
|
||||
for i in 0 1; do
|
||||
kill -s $sig $pids
|
||||
for j in 0 1 2; do
|
||||
cgroup_get_pids || { eend 0 "finished" ; return 0 ; }
|
||||
sleep 1
|
||||
done
|
||||
done 2>/dev/null
|
||||
done
|
||||
cgroup_get_pids || { eend 0 "finished" ; return 0; }
|
||||
kill -9 $pids
|
||||
eend $(cgroup_running && echo 1 || echo 0) "fail to stop all processes"
|
||||
local pids
|
||||
pids="$(cgroup_get_pids)"
|
||||
if [ -n "${pids}" ]; then
|
||||
kill -s "${stopsig:-TERM}" ${pids} 2> /dev/null
|
||||
kill -s CONT ${pids} 2> /dev/null
|
||||
yesno "${rc_send_sighup:-no}" &&
|
||||
kill -s HUP ${pids} 2> /dev/null
|
||||
sleep "${rc_timeout_stopsec:-90}"
|
||||
yesno "${rc_send_sigkill:-yes}" &&
|
||||
kill -s KILL ${pids} 2> /dev/null
|
||||
fi
|
||||
cgroup2_remove
|
||||
[ -z "$(cgroup_get_pids)" ]
|
||||
eend $? "Unable to stop all processes"
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ supervise_start()
|
||||
# command_args="this \"is a\" test"
|
||||
# to work properly.
|
||||
eval supervise-daemon --start \
|
||||
${retry:+--retry} $retry \
|
||||
${chroot:+--chroot} $chroot \
|
||||
${pidfile:+--pidfile} $pidfile \
|
||||
${respawn_delay:+--respawn-delay} $respawn_delay \
|
||||
|
||||
@@ -71,5 +71,6 @@ bool _rc_can_find_pids(void);
|
||||
RC_SERVICE lookup_service_state(const char *service);
|
||||
void from_time_t(char *time_string, time_t tv);
|
||||
time_t to_time_t(char *timestring);
|
||||
pid_t get_pid(const char *applet, const char *pidfile);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -156,10 +156,10 @@ rc-service service: rc-service.o _usage.o rc-misc.o
|
||||
rc-update: rc-update.o _usage.o rc-misc.o
|
||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||
|
||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o
|
||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-schedules.o
|
||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||
|
||||
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o
|
||||
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o
|
||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||
|
||||
service_get_value service_set_value get_options save_options: do_value.o rc-misc.o
|
||||
|
||||
@@ -474,3 +474,27 @@ time_t to_time_t(char *timestring)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pid_t get_pid(const char *applet,const char *pidfile)
|
||||
{
|
||||
FILE *fp;
|
||||
pid_t pid;
|
||||
|
||||
if (! pidfile)
|
||||
return -1;
|
||||
|
||||
if ((fp = fopen(pidfile, "r")) == NULL) {
|
||||
ewarnv("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fscanf(fp, "%d", &pid) != 1) {
|
||||
ewarnv("%s: no pid found in `%s'", applet, pidfile);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
418
src/rc/rc-schedules.c
Normal file
418
src/rc/rc-schedules.c
Normal file
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* The functions in this file control the stopping of daemons by
|
||||
* start-stop-daemon and supervise-daemon.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 The OpenRC Authors.
|
||||
* See the Authors file at the top-level directory of this distribution and
|
||||
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
|
||||
*
|
||||
* This file is part of OpenRC. It is subject to the license terms in
|
||||
* the LICENSE file found in the top-level directory of this
|
||||
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
||||
* This file may not be copied, modified, propagated, or distributed
|
||||
* except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* nano seconds */
|
||||
#define POLL_INTERVAL 20000000
|
||||
#define WAIT_PIDFILE 500000000
|
||||
#define ONE_SECOND 1000000000
|
||||
#define ONE_MS 1000000
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "einfo.h"
|
||||
#include "queue.h"
|
||||
#include "rc.h"
|
||||
#include "rc-misc.h"
|
||||
#include "rc-schedules.h"
|
||||
#include "helpers.h"
|
||||
|
||||
typedef struct scheduleitem {
|
||||
enum {
|
||||
SC_TIMEOUT,
|
||||
SC_SIGNAL,
|
||||
SC_GOTO,
|
||||
SC_FOREVER,
|
||||
} type;
|
||||
int value;
|
||||
struct scheduleitem *gotoitem;
|
||||
TAILQ_ENTRY(scheduleitem) entries;
|
||||
} SCHEDULEITEM;
|
||||
|
||||
static TAILQ_HEAD(, scheduleitem) schedule;
|
||||
|
||||
void free_schedulelist(void)
|
||||
{
|
||||
SCHEDULEITEM *s1 = TAILQ_FIRST(&schedule);
|
||||
SCHEDULEITEM *s2;
|
||||
|
||||
while (s1) {
|
||||
s2 = TAILQ_NEXT(s1, entries);
|
||||
free(s1);
|
||||
s1 = s2;
|
||||
}
|
||||
TAILQ_INIT(&schedule);
|
||||
}
|
||||
|
||||
int parse_signal(const char *applet, const char *sig)
|
||||
{
|
||||
typedef struct signalpair
|
||||
{
|
||||
const char *name;
|
||||
int signal;
|
||||
} SIGNALPAIR;
|
||||
|
||||
#define signalpair_item(name) { #name, SIG##name },
|
||||
|
||||
static const SIGNALPAIR signallist[] = {
|
||||
signalpair_item(HUP)
|
||||
signalpair_item(INT)
|
||||
signalpair_item(QUIT)
|
||||
signalpair_item(ILL)
|
||||
signalpair_item(TRAP)
|
||||
signalpair_item(ABRT)
|
||||
signalpair_item(BUS)
|
||||
signalpair_item(FPE)
|
||||
signalpair_item(KILL)
|
||||
signalpair_item(USR1)
|
||||
signalpair_item(SEGV)
|
||||
signalpair_item(USR2)
|
||||
signalpair_item(PIPE)
|
||||
signalpair_item(ALRM)
|
||||
signalpair_item(TERM)
|
||||
signalpair_item(CHLD)
|
||||
signalpair_item(CONT)
|
||||
signalpair_item(STOP)
|
||||
signalpair_item(TSTP)
|
||||
signalpair_item(TTIN)
|
||||
signalpair_item(TTOU)
|
||||
signalpair_item(URG)
|
||||
signalpair_item(XCPU)
|
||||
signalpair_item(XFSZ)
|
||||
signalpair_item(VTALRM)
|
||||
signalpair_item(PROF)
|
||||
#ifdef SIGWINCH
|
||||
signalpair_item(WINCH)
|
||||
#endif
|
||||
#ifdef SIGIO
|
||||
signalpair_item(IO)
|
||||
#endif
|
||||
#ifdef SIGPWR
|
||||
signalpair_item(PWR)
|
||||
#endif
|
||||
signalpair_item(SYS)
|
||||
{ "NULL", 0 },
|
||||
};
|
||||
|
||||
unsigned int i = 0;
|
||||
const char *s;
|
||||
|
||||
if (!sig || *sig == '\0')
|
||||
return -1;
|
||||
|
||||
if (sscanf(sig, "%u", &i) == 1) {
|
||||
if (i < NSIG)
|
||||
return i;
|
||||
eerrorx("%s: `%s' is not a valid signal", applet, sig);
|
||||
}
|
||||
|
||||
if (strncmp(sig, "SIG", 3) == 0)
|
||||
s = sig + 3;
|
||||
else
|
||||
s = NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(signallist); ++i)
|
||||
if (strcmp(sig, signallist[i].name) == 0 ||
|
||||
(s && strcmp(s, signallist[i].name) == 0))
|
||||
return signallist[i].signal;
|
||||
|
||||
eerrorx("%s: `%s' is not a valid signal", applet, sig);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static SCHEDULEITEM *parse_schedule_item(const char *applet, const char *string)
|
||||
{
|
||||
const char *after_hyph;
|
||||
int sig;
|
||||
SCHEDULEITEM *item = xmalloc(sizeof(*item));
|
||||
|
||||
item->value = 0;
|
||||
item->gotoitem = NULL;
|
||||
if (strcmp(string,"forever") == 0)
|
||||
item->type = SC_FOREVER;
|
||||
else if (isdigit((unsigned char)string[0])) {
|
||||
item->type = SC_TIMEOUT;
|
||||
errno = 0;
|
||||
if (sscanf(string, "%d", &item->value) != 1)
|
||||
eerrorx("%s: invalid timeout value in schedule `%s'",
|
||||
applet, string);
|
||||
} else if ((after_hyph = string + (string[0] == '-')) &&
|
||||
((sig = parse_signal(applet, after_hyph)) != -1))
|
||||
{
|
||||
item->type = SC_SIGNAL;
|
||||
item->value = (int)sig;
|
||||
} else
|
||||
eerrorx("%s: invalid schedule item `%s'", applet, string);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void parse_schedule(const char *applet, const char *string, int timeout)
|
||||
{
|
||||
char buffer[20];
|
||||
const char *slash;
|
||||
int count = 0;
|
||||
SCHEDULEITEM *repeatat = NULL;
|
||||
size_t len;
|
||||
SCHEDULEITEM *item;
|
||||
|
||||
TAILQ_INIT(&schedule);
|
||||
if (string)
|
||||
for (slash = string; *slash; slash++)
|
||||
if (*slash == '/')
|
||||
count++;
|
||||
|
||||
free_schedulelist();
|
||||
|
||||
if (count == 0) {
|
||||
item = xmalloc(sizeof(*item));
|
||||
item->type = SC_SIGNAL;
|
||||
item->value = timeout;
|
||||
item->gotoitem = NULL;
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
|
||||
item = xmalloc(sizeof(*item));
|
||||
item->type = SC_TIMEOUT;
|
||||
item->gotoitem = NULL;
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
if (string) {
|
||||
if (sscanf(string, "%d", &item->value) != 1)
|
||||
eerrorx("%s: invalid timeout in schedule",
|
||||
applet);
|
||||
} else
|
||||
item->value = 5;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while (string != NULL) {
|
||||
if ((slash = strchr(string, '/')))
|
||||
len = slash - string;
|
||||
else
|
||||
len = strlen(string);
|
||||
|
||||
if (len >= (ptrdiff_t)sizeof(buffer))
|
||||
eerrorx("%s: invalid schedule item, far too long",
|
||||
applet);
|
||||
|
||||
memcpy(buffer, string, len);
|
||||
buffer[len] = 0;
|
||||
string = slash ? slash + 1 : NULL;
|
||||
|
||||
item = parse_schedule_item(applet, buffer);
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
if (item->type == SC_FOREVER) {
|
||||
if (repeatat)
|
||||
eerrorx("%s: invalid schedule, `forever' "
|
||||
"appears more than once", applet);
|
||||
|
||||
repeatat = item;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (repeatat) {
|
||||
item = xmalloc(sizeof(*item));
|
||||
item->type = SC_GOTO;
|
||||
item->value = 0;
|
||||
item->gotoitem = repeatat;
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* return number of processes killed, -1 on error */
|
||||
int do_stop(const char *applet, const char *exec, const char *const *argv,
|
||||
pid_t pid, uid_t uid,int sig, bool test, bool quiet)
|
||||
{
|
||||
RC_PIDLIST *pids;
|
||||
RC_PID *pi;
|
||||
RC_PID *np;
|
||||
bool killed;
|
||||
int nkilled = 0;
|
||||
|
||||
if (pid > 0)
|
||||
pids = rc_find_pids(NULL, NULL, 0, pid);
|
||||
else
|
||||
pids = rc_find_pids(exec, argv, uid, 0);
|
||||
|
||||
if (!pids)
|
||||
return 0;
|
||||
|
||||
LIST_FOREACH_SAFE(pi, pids, entries, np) {
|
||||
if (test) {
|
||||
einfo("Would send signal %d to PID %d", sig, pi->pid);
|
||||
nkilled++;
|
||||
} else {
|
||||
if (!quiet)
|
||||
ebeginv("Sending signal %d to PID %d", sig, pi->pid);
|
||||
errno = 0;
|
||||
killed = (kill(pi->pid, sig) == 0 ||
|
||||
errno == ESRCH ? true : false);
|
||||
if (! quiet)
|
||||
eendv(killed ? 0 : 1,
|
||||
"%s: failed to send signal %d to PID %d: %s",
|
||||
applet, sig, pi->pid, strerror(errno));
|
||||
if (!killed) {
|
||||
nkilled = -1;
|
||||
} else {
|
||||
if (nkilled != -1)
|
||||
nkilled++;
|
||||
}
|
||||
}
|
||||
free(pi);
|
||||
}
|
||||
|
||||
free(pids);
|
||||
return nkilled;
|
||||
}
|
||||
|
||||
int run_stop_schedule(const char *applet,
|
||||
const char *exec, const char *const *argv,
|
||||
pid_t pid, uid_t uid,
|
||||
bool test, bool progress, bool quiet)
|
||||
{
|
||||
SCHEDULEITEM *item = TAILQ_FIRST(&schedule);
|
||||
int nkilled = 0;
|
||||
int tkilled = 0;
|
||||
int nrunning = 0;
|
||||
long nloops, nsecs;
|
||||
struct timespec ts;
|
||||
const char *const *p;
|
||||
bool progressed = false;
|
||||
|
||||
if (exec)
|
||||
einfov("Will stop %s", exec);
|
||||
if (pid > 0)
|
||||
einfov("Will stop PID %d", pid);
|
||||
if (uid)
|
||||
einfov("Will stop processes owned by UID %d", uid);
|
||||
if (argv && *argv) {
|
||||
einfovn("Will stop processes of `");
|
||||
if (rc_yesno(getenv("EINFO_VERBOSE"))) {
|
||||
for (p = argv; p && *p; p++) {
|
||||
if (p != argv)
|
||||
printf(" ");
|
||||
printf("%s", *p);
|
||||
}
|
||||
printf("'\n");
|
||||
}
|
||||
}
|
||||
|
||||
while (item) {
|
||||
switch (item->type) {
|
||||
case SC_GOTO:
|
||||
item = item->gotoitem;
|
||||
continue;
|
||||
|
||||
case SC_SIGNAL:
|
||||
nrunning = 0;
|
||||
nkilled = do_stop(applet, exec, argv, pid, uid, item->value, test,
|
||||
quiet);
|
||||
if (nkilled == 0) {
|
||||
if (tkilled == 0) {
|
||||
if (progressed)
|
||||
printf("\n");
|
||||
eerror("%s: no matching processes found", applet);
|
||||
}
|
||||
return tkilled;
|
||||
}
|
||||
else if (nkilled == -1)
|
||||
return 0;
|
||||
|
||||
tkilled += nkilled;
|
||||
break;
|
||||
case SC_TIMEOUT:
|
||||
if (item->value < 1) {
|
||||
item = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = POLL_INTERVAL;
|
||||
|
||||
for (nsecs = 0; nsecs < item->value; nsecs++) {
|
||||
for (nloops = 0;
|
||||
nloops < ONE_SECOND / POLL_INTERVAL;
|
||||
nloops++)
|
||||
{
|
||||
if ((nrunning = do_stop(applet, exec, argv,
|
||||
pid, uid, 0, test, quiet)) == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
if (nanosleep(&ts, NULL) == -1) {
|
||||
if (progressed) {
|
||||
printf("\n");
|
||||
progressed = false;
|
||||
}
|
||||
if (errno == EINTR)
|
||||
eerror("%s: caught an"
|
||||
" interrupt", applet);
|
||||
else {
|
||||
eerror("%s: nanosleep: %s",
|
||||
applet, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (progress) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
progressed = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (progressed) {
|
||||
printf("\n");
|
||||
progressed = false;
|
||||
}
|
||||
eerror("%s: invalid schedule item `%d'",
|
||||
applet, item->type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (item)
|
||||
item = TAILQ_NEXT(item, entries);
|
||||
}
|
||||
|
||||
if (test || (tkilled > 0 && nrunning == 0))
|
||||
return nkilled;
|
||||
|
||||
if (progressed)
|
||||
printf("\n");
|
||||
if (! quiet)
|
||||
if (nrunning == 1)
|
||||
eerror("%s: %d process refused to stop", applet, nrunning);
|
||||
else
|
||||
eerror("%s: %d process(es) refused to stop", applet, nrunning);
|
||||
|
||||
return -nrunning;
|
||||
}
|
||||
26
src/rc/rc-schedules.h
Normal file
26
src/rc/rc-schedules.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The OpenRC Authors.
|
||||
* See the Authors file at the top-level directory of this distribution and
|
||||
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
|
||||
*
|
||||
* This file is part of OpenRC. It is subject to the license terms in
|
||||
* the LICENSE file found in the top-level directory of this
|
||||
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
||||
* This file may not be copied, modified, propagated, or distributed
|
||||
* except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef __RC_SCHEDULES_H
|
||||
#define __RC_SCHEDULES_H
|
||||
|
||||
void free_schedulelist(void);
|
||||
int parse_signal(const char *applet, const char *sig);
|
||||
void parse_schedule(const char *applet, const char *string, int timeout);
|
||||
int do_stop(const char *applet, const char *exec, const char *const *argv,
|
||||
pid_t pid, uid_t uid,int sig, bool test, bool quiet);
|
||||
int run_stop_schedule(const char *applet,
|
||||
const char *exec, const char *const *argv,
|
||||
pid_t pid, uid_t uid,
|
||||
bool test, bool progress, bool quiet);
|
||||
|
||||
#endif
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "rc-selinux.h"
|
||||
|
||||
/* the context files for selinux */
|
||||
#define RUN_INIT_FILE "run_init_type"
|
||||
#define INITRC_FILE "initrc_context"
|
||||
|
||||
#ifdef HAVE_AUDIT
|
||||
@@ -299,6 +298,26 @@ static int read_context_file(const char *filename, char **context)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int read_run_init_context(char **context)
|
||||
{
|
||||
int ret = -1;
|
||||
RC_STRINGLIST *list;
|
||||
char *value = NULL;
|
||||
|
||||
list = rc_config_list(selinux_openrc_contexts_path());
|
||||
if (list == NULL)
|
||||
return ret;
|
||||
|
||||
value = rc_config_value(list, "run_init");
|
||||
if (value != NULL && strlen(value) > 0) {
|
||||
*context = xstrdup(value);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
rc_stringlist_free(list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void selinux_setup(char **argv)
|
||||
{
|
||||
char *new_context = NULL;
|
||||
@@ -312,7 +331,7 @@ void selinux_setup(char **argv)
|
||||
return;
|
||||
}
|
||||
|
||||
if (read_context_file(RUN_INIT_FILE, &run_init_t) != 0) {
|
||||
if (read_run_init_context(&run_init_t) != 0) {
|
||||
/* assume a reasonable default, rather than bailing out */
|
||||
run_init_t = xstrdup("run_init_t");
|
||||
ewarn("Assuming SELinux run_init type is %s", run_init_t);
|
||||
@@ -339,14 +358,13 @@ void selinux_setup(char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
curr_t = context_type_get(curr_con);
|
||||
curr_t = xstrdup(context_type_get(curr_con));
|
||||
if (!curr_t) {
|
||||
context_free(curr_con);
|
||||
free(curr_context);
|
||||
goto out;
|
||||
}
|
||||
|
||||
curr_t = xstrdup(curr_t);
|
||||
/* dont need them anymore so free() now */
|
||||
context_free(curr_con);
|
||||
free(curr_context);
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
* except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
/* nano seconds */
|
||||
#define POLL_INTERVAL 20000000
|
||||
#define WAIT_PIDFILE 500000000
|
||||
#define ONE_SECOND 1000000000
|
||||
#define ONE_MS 1000000
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -63,6 +59,7 @@ static struct pam_conv conv = { NULL, NULL};
|
||||
#include "queue.h"
|
||||
#include "rc.h"
|
||||
#include "rc-misc.h"
|
||||
#include "rc-schedules.h"
|
||||
#include "_usage.h"
|
||||
#include "helpers.h"
|
||||
|
||||
@@ -130,20 +127,6 @@ const char * const longopts_help[] = {
|
||||
};
|
||||
const char *usagestring = NULL;
|
||||
|
||||
typedef struct scheduleitem
|
||||
{
|
||||
enum
|
||||
{
|
||||
SC_TIMEOUT,
|
||||
SC_SIGNAL,
|
||||
SC_GOTO,
|
||||
SC_FOREVER
|
||||
} type;
|
||||
int value;
|
||||
struct scheduleitem *gotoitem;
|
||||
TAILQ_ENTRY(scheduleitem) entries;
|
||||
} SCHEDULEITEM;
|
||||
TAILQ_HEAD(, scheduleitem) schedule;
|
||||
static char **nav;
|
||||
|
||||
static char *changeuser, *ch_root, *ch_dir;
|
||||
@@ -166,20 +149,6 @@ static inline int ioprio_set(int which _unused,
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
free_schedulelist(void)
|
||||
{
|
||||
SCHEDULEITEM *s1 = TAILQ_FIRST(&schedule);
|
||||
SCHEDULEITEM *s2;
|
||||
|
||||
while (s1) {
|
||||
s2 = TAILQ_NEXT(s1, entries);
|
||||
free(s1);
|
||||
s1 = s2;
|
||||
}
|
||||
TAILQ_INIT(&schedule);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup(void)
|
||||
{
|
||||
@@ -188,385 +157,6 @@ cleanup(void)
|
||||
free_schedulelist();
|
||||
}
|
||||
|
||||
static int
|
||||
parse_signal(const char *sig)
|
||||
{
|
||||
typedef struct signalpair
|
||||
{
|
||||
const char *name;
|
||||
int signal;
|
||||
} SIGNALPAIR;
|
||||
|
||||
#define signalpair_item(name) { #name, SIG##name },
|
||||
|
||||
static const SIGNALPAIR signallist[] = {
|
||||
signalpair_item(HUP)
|
||||
signalpair_item(INT)
|
||||
signalpair_item(QUIT)
|
||||
signalpair_item(ILL)
|
||||
signalpair_item(TRAP)
|
||||
signalpair_item(ABRT)
|
||||
signalpair_item(BUS)
|
||||
signalpair_item(FPE)
|
||||
signalpair_item(KILL)
|
||||
signalpair_item(USR1)
|
||||
signalpair_item(SEGV)
|
||||
signalpair_item(USR2)
|
||||
signalpair_item(PIPE)
|
||||
signalpair_item(ALRM)
|
||||
signalpair_item(TERM)
|
||||
signalpair_item(CHLD)
|
||||
signalpair_item(CONT)
|
||||
signalpair_item(STOP)
|
||||
signalpair_item(TSTP)
|
||||
signalpair_item(TTIN)
|
||||
signalpair_item(TTOU)
|
||||
signalpair_item(URG)
|
||||
signalpair_item(XCPU)
|
||||
signalpair_item(XFSZ)
|
||||
signalpair_item(VTALRM)
|
||||
signalpair_item(PROF)
|
||||
#ifdef SIGWINCH
|
||||
signalpair_item(WINCH)
|
||||
#endif
|
||||
#ifdef SIGIO
|
||||
signalpair_item(IO)
|
||||
#endif
|
||||
#ifdef SIGPWR
|
||||
signalpair_item(PWR)
|
||||
#endif
|
||||
signalpair_item(SYS)
|
||||
{ "NULL", 0 },
|
||||
};
|
||||
|
||||
unsigned int i = 0;
|
||||
const char *s;
|
||||
|
||||
if (!sig || *sig == '\0')
|
||||
return -1;
|
||||
|
||||
if (sscanf(sig, "%u", &i) == 1) {
|
||||
if (i < NSIG)
|
||||
return i;
|
||||
eerrorx("%s: `%s' is not a valid signal", applet, sig);
|
||||
}
|
||||
|
||||
if (strncmp(sig, "SIG", 3) == 0)
|
||||
s = sig + 3;
|
||||
else
|
||||
s = NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(signallist); ++i)
|
||||
if (strcmp(sig, signallist[i].name) == 0 ||
|
||||
(s && strcmp(s, signallist[i].name) == 0))
|
||||
return signallist[i].signal;
|
||||
|
||||
eerrorx("%s: `%s' is not a valid signal", applet, sig);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static SCHEDULEITEM *
|
||||
parse_schedule_item(const char *string)
|
||||
{
|
||||
const char *after_hyph;
|
||||
int sig;
|
||||
SCHEDULEITEM *item = xmalloc(sizeof(*item));
|
||||
|
||||
item->value = 0;
|
||||
item->gotoitem = NULL;
|
||||
if (strcmp(string,"forever") == 0)
|
||||
item->type = SC_FOREVER;
|
||||
else if (isdigit((unsigned char)string[0])) {
|
||||
item->type = SC_TIMEOUT;
|
||||
errno = 0;
|
||||
if (sscanf(string, "%d", &item->value) != 1)
|
||||
eerrorx("%s: invalid timeout value in schedule `%s'",
|
||||
applet, string);
|
||||
} else if ((after_hyph = string + (string[0] == '-')) &&
|
||||
((sig = parse_signal(after_hyph)) != -1))
|
||||
{
|
||||
item->type = SC_SIGNAL;
|
||||
item->value = (int)sig;
|
||||
} else
|
||||
eerrorx("%s: invalid schedule item `%s'", applet, string);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_schedule(const char *string, int timeout)
|
||||
{
|
||||
char buffer[20];
|
||||
const char *slash;
|
||||
int count = 0;
|
||||
SCHEDULEITEM *repeatat = NULL;
|
||||
size_t len;
|
||||
SCHEDULEITEM *item;
|
||||
|
||||
if (string)
|
||||
for (slash = string; *slash; slash++)
|
||||
if (*slash == '/')
|
||||
count++;
|
||||
|
||||
free_schedulelist();
|
||||
|
||||
if (count == 0) {
|
||||
item = xmalloc(sizeof(*item));
|
||||
item->type = SC_SIGNAL;
|
||||
item->value = timeout;
|
||||
item->gotoitem = NULL;
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
|
||||
item = xmalloc(sizeof(*item));
|
||||
item->type = SC_TIMEOUT;
|
||||
item->gotoitem = NULL;
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
if (string) {
|
||||
if (sscanf(string, "%d", &item->value) != 1)
|
||||
eerrorx("%s: invalid timeout in schedule",
|
||||
applet);
|
||||
} else
|
||||
item->value = 5;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while (string != NULL) {
|
||||
if ((slash = strchr(string, '/')))
|
||||
len = slash - string;
|
||||
else
|
||||
len = strlen(string);
|
||||
|
||||
if (len >= (ptrdiff_t)sizeof(buffer))
|
||||
eerrorx("%s: invalid schedule item, far too long",
|
||||
applet);
|
||||
|
||||
memcpy(buffer, string, len);
|
||||
buffer[len] = 0;
|
||||
string = slash ? slash + 1 : NULL;
|
||||
|
||||
item = parse_schedule_item(buffer);
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
if (item->type == SC_FOREVER) {
|
||||
if (repeatat)
|
||||
eerrorx("%s: invalid schedule, `forever' "
|
||||
"appears more than once", applet);
|
||||
|
||||
repeatat = item;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (repeatat) {
|
||||
item = xmalloc(sizeof(*item));
|
||||
item->type = SC_GOTO;
|
||||
item->value = 0;
|
||||
item->gotoitem = repeatat;
|
||||
TAILQ_INSERT_TAIL(&schedule, item, entries);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static pid_t
|
||||
get_pid(const char *pidfile)
|
||||
{
|
||||
FILE *fp;
|
||||
pid_t pid;
|
||||
|
||||
if (! pidfile)
|
||||
return -1;
|
||||
|
||||
if ((fp = fopen(pidfile, "r")) == NULL) {
|
||||
ewarnv("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fscanf(fp, "%d", &pid) != 1) {
|
||||
ewarnv("%s: no pid found in `%s'", applet, pidfile);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
/* return number of processed killed, -1 on error */
|
||||
static int
|
||||
do_stop(const char *exec, const char *const *argv,
|
||||
pid_t pid, uid_t uid,int sig, bool test)
|
||||
{
|
||||
RC_PIDLIST *pids;
|
||||
RC_PID *pi;
|
||||
RC_PID *np;
|
||||
bool killed;
|
||||
int nkilled = 0;
|
||||
|
||||
if (pid)
|
||||
pids = rc_find_pids(NULL, NULL, 0, pid);
|
||||
else
|
||||
pids = rc_find_pids(exec, argv, uid, pid);
|
||||
|
||||
if (!pids)
|
||||
return 0;
|
||||
|
||||
LIST_FOREACH_SAFE(pi, pids, entries, np) {
|
||||
if (test) {
|
||||
einfo("Would send signal %d to PID %d", sig, pi->pid);
|
||||
nkilled++;
|
||||
} else {
|
||||
ebeginv("Sending signal %d to PID %d", sig, pi->pid);
|
||||
errno = 0;
|
||||
killed = (kill(pi->pid, sig) == 0 ||
|
||||
errno == ESRCH ? true : false);
|
||||
eendv(killed ? 0 : 1,
|
||||
"%s: failed to send signal %d to PID %d: %s",
|
||||
applet, sig, pi->pid, strerror(errno));
|
||||
if (!killed) {
|
||||
nkilled = -1;
|
||||
} else {
|
||||
if (nkilled != -1)
|
||||
nkilled++;
|
||||
}
|
||||
}
|
||||
free(pi);
|
||||
}
|
||||
|
||||
free(pids);
|
||||
return nkilled;
|
||||
}
|
||||
|
||||
static int
|
||||
run_stop_schedule(const char *exec, const char *const *argv,
|
||||
const char *pidfile, uid_t uid,
|
||||
bool test, bool progress)
|
||||
{
|
||||
SCHEDULEITEM *item = TAILQ_FIRST(&schedule);
|
||||
int nkilled = 0;
|
||||
int tkilled = 0;
|
||||
int nrunning = 0;
|
||||
long nloops, nsecs;
|
||||
struct timespec ts;
|
||||
pid_t pid = 0;
|
||||
const char *const *p;
|
||||
bool progressed = false;
|
||||
|
||||
if (exec)
|
||||
einfov("Will stop %s", exec);
|
||||
if (pidfile)
|
||||
einfov("Will stop PID in pidfile `%s'", pidfile);
|
||||
if (uid)
|
||||
einfov("Will stop processes owned by UID %d", uid);
|
||||
if (argv && *argv) {
|
||||
einfovn("Will stop processes of `");
|
||||
if (rc_yesno(getenv("EINFO_VERBOSE"))) {
|
||||
for (p = argv; p && *p; p++) {
|
||||
if (p != argv)
|
||||
printf(" ");
|
||||
printf("%s", *p);
|
||||
}
|
||||
printf("'\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (pidfile) {
|
||||
pid = get_pid(pidfile);
|
||||
if (pid == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (item) {
|
||||
switch (item->type) {
|
||||
case SC_GOTO:
|
||||
item = item->gotoitem;
|
||||
continue;
|
||||
|
||||
case SC_SIGNAL:
|
||||
nrunning = 0;
|
||||
nkilled = do_stop(exec, argv, pid, uid, item->value, test);
|
||||
if (nkilled == 0) {
|
||||
if (tkilled == 0) {
|
||||
if (progressed)
|
||||
printf("\n");
|
||||
eerror("%s: no matching processes found", applet);
|
||||
}
|
||||
return tkilled;
|
||||
}
|
||||
else if (nkilled == -1)
|
||||
return 0;
|
||||
|
||||
tkilled += nkilled;
|
||||
break;
|
||||
case SC_TIMEOUT:
|
||||
if (item->value < 1) {
|
||||
item = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = POLL_INTERVAL;
|
||||
|
||||
for (nsecs = 0; nsecs < item->value; nsecs++) {
|
||||
for (nloops = 0;
|
||||
nloops < ONE_SECOND / POLL_INTERVAL;
|
||||
nloops++)
|
||||
{
|
||||
if ((nrunning = do_stop(exec, argv,
|
||||
pid, uid, 0, test)) == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
if (nanosleep(&ts, NULL) == -1) {
|
||||
if (progressed) {
|
||||
printf("\n");
|
||||
progressed = false;
|
||||
}
|
||||
if (errno == EINTR)
|
||||
eerror("%s: caught an"
|
||||
" interrupt", applet);
|
||||
else {
|
||||
eerror("%s: nanosleep: %s",
|
||||
applet, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (progress) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
progressed = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (progressed) {
|
||||
printf("\n");
|
||||
progressed = false;
|
||||
}
|
||||
eerror("%s: invalid schedule item `%d'",
|
||||
applet, item->type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (item)
|
||||
item = TAILQ_NEXT(item, entries);
|
||||
}
|
||||
|
||||
if (test || (tkilled > 0 && nrunning == 0))
|
||||
return nkilled;
|
||||
|
||||
if (progressed)
|
||||
printf("\n");
|
||||
if (nrunning == 1)
|
||||
eerror("%s: %d process refused to stop", applet, nrunning);
|
||||
else
|
||||
eerror("%s: %d process(es) refused to stop", applet, nrunning);
|
||||
|
||||
return -nrunning;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_signal(int sig)
|
||||
{
|
||||
@@ -707,7 +297,6 @@ int main(int argc, char **argv)
|
||||
unsigned int start_wait = 0;
|
||||
|
||||
applet = basename_c(argv[0]);
|
||||
TAILQ_INIT(&schedule);
|
||||
atexit(cleanup);
|
||||
|
||||
signal_setup(SIGINT, handle_signal);
|
||||
@@ -876,7 +465,7 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 's': /* --signal <signal> */
|
||||
sig = parse_signal(optarg);
|
||||
sig = parse_signal(applet, optarg);
|
||||
break;
|
||||
|
||||
case 't': /* --test */
|
||||
@@ -1062,13 +651,13 @@ int main(int argc, char **argv)
|
||||
if (!stop)
|
||||
oknodo = true;
|
||||
if (retry)
|
||||
parse_schedule(retry, sig);
|
||||
parse_schedule(applet, retry, sig);
|
||||
else if (test || oknodo)
|
||||
parse_schedule("0", sig);
|
||||
parse_schedule(applet, "0", sig);
|
||||
else
|
||||
parse_schedule(NULL, sig);
|
||||
i = run_stop_schedule(exec, (const char *const *)margv,
|
||||
pidfile, uid, test, progress);
|
||||
parse_schedule(applet, NULL, sig);
|
||||
i = run_stop_schedule(applet, exec, (const char *const *)margv,
|
||||
get_pid(applet, pidfile), uid, test, progress, false);
|
||||
|
||||
if (i < 0)
|
||||
/* We failed to stop something */
|
||||
@@ -1090,12 +679,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (pidfile)
|
||||
pid = get_pid(pidfile);
|
||||
pid = get_pid(applet, pidfile);
|
||||
else
|
||||
pid = 0;
|
||||
|
||||
if (do_stop(exec, (const char * const *)margv, pid, uid,
|
||||
0, test) > 0)
|
||||
if (do_stop(applet, exec, (const char * const *)margv, pid, uid,
|
||||
0, test, false) > 0)
|
||||
eerrorx("%s: %s is already running", applet, exec);
|
||||
|
||||
if (test) {
|
||||
@@ -1365,7 +954,7 @@ int main(int argc, char **argv)
|
||||
alive = true;
|
||||
} else {
|
||||
if (pidfile) {
|
||||
pid = get_pid(pidfile);
|
||||
pid = get_pid(applet, pidfile);
|
||||
if (pid == -1) {
|
||||
eerrorx("%s: did not "
|
||||
"create a valid"
|
||||
@@ -1374,8 +963,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
} else
|
||||
pid = 0;
|
||||
if (do_stop(exec, (const char *const *)margv,
|
||||
pid, uid, 0, test) > 0)
|
||||
if (do_stop(applet, exec, (const char *const *)margv,
|
||||
pid, uid, 0, test, false) > 0)
|
||||
alive = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,12 +61,13 @@ static struct pam_conv conv = { NULL, NULL};
|
||||
#include "queue.h"
|
||||
#include "rc.h"
|
||||
#include "rc-misc.h"
|
||||
#include "rc-schedules.h"
|
||||
#include "_usage.h"
|
||||
#include "helpers.h"
|
||||
|
||||
const char *applet = NULL;
|
||||
const char *extraopts = NULL;
|
||||
const char *getoptstring = "D:d:e:g:I:Kk:m:N:p:r:Su:1:2:" \
|
||||
const char *getoptstring = "D:d:e:g:I:Kk:m:N:p:R:r:Su:1:2:" \
|
||||
getoptstring_COMMON;
|
||||
const struct option longopts[] = {
|
||||
{ "respawn-delay", 1, NULL, 'D'},
|
||||
@@ -80,6 +81,7 @@ const struct option longopts[] = {
|
||||
{ "nicelevel", 1, NULL, 'N'},
|
||||
{ "pidfile", 1, NULL, 'p'},
|
||||
{ "respawn-period", 1, NULL, 'P'},
|
||||
{ "retry", 1, NULL, 'R'},
|
||||
{ "chroot", 1, NULL, 'r'},
|
||||
{ "start", 0, NULL, 'S'},
|
||||
{ "user", 1, NULL, 'u'},
|
||||
@@ -99,6 +101,7 @@ const char * const longopts_help[] = {
|
||||
"Set a nicelevel when starting",
|
||||
"Match pid found in this file",
|
||||
"Set respawn time period",
|
||||
"Retry schedule to use when stopping",
|
||||
"Chroot to this directory",
|
||||
"Start daemon",
|
||||
"Change the process user",
|
||||
@@ -147,30 +150,6 @@ static void cleanup(void)
|
||||
free(changeuser);
|
||||
}
|
||||
|
||||
static pid_t get_pid(const char *pidfile)
|
||||
{
|
||||
FILE *fp;
|
||||
pid_t pid;
|
||||
|
||||
if (! pidfile)
|
||||
return -1;
|
||||
|
||||
if ((fp = fopen(pidfile, "r")) == NULL) {
|
||||
ewarnv("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fscanf(fp, "%d", &pid) != 1) {
|
||||
ewarnv("%s: no pid found in `%s'", applet, pidfile);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
static void child_process(char *exec, char **argv, char *svcname,
|
||||
int start_count)
|
||||
{
|
||||
@@ -434,6 +413,9 @@ int main(int argc, char **argv)
|
||||
bool stop = false;
|
||||
char *exec = NULL;
|
||||
char *pidfile = NULL;
|
||||
char *retry = NULL;
|
||||
int nkilled;
|
||||
int sig = SIGTERM;
|
||||
char *home = NULL;
|
||||
int tid = 0;
|
||||
pid_t child_pid, pid;
|
||||
@@ -450,6 +432,7 @@ int main(int argc, char **argv)
|
||||
int respawn_period = 5;
|
||||
time_t respawn_now= 0;
|
||||
time_t first_spawn= 0;
|
||||
struct timespec ts;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
FILE *fp;
|
||||
@@ -458,11 +441,6 @@ int main(int argc, char **argv)
|
||||
applet = basename_c(argv[0]);
|
||||
atexit(cleanup);
|
||||
|
||||
signal_setup(SIGINT, handle_signal);
|
||||
signal_setup(SIGQUIT, handle_signal);
|
||||
signal_setup(SIGTERM, handle_signal);
|
||||
openlog(applet, LOG_PID, LOG_DAEMON);
|
||||
|
||||
if ((tmp = getenv("SSD_NICELEVEL")))
|
||||
if (sscanf(tmp, "%d", &nicelevel) != 1)
|
||||
eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
|
||||
@@ -558,6 +536,9 @@ int main(int argc, char **argv)
|
||||
pidfile = optarg;
|
||||
break;
|
||||
|
||||
case 'R': /* --retry <schedule>|timeout */
|
||||
retry = optarg;
|
||||
break;
|
||||
case 'r': /* --chroot /new/root */
|
||||
ch_root = optarg;
|
||||
break;
|
||||
@@ -629,6 +610,10 @@ int main(int argc, char **argv)
|
||||
"than %d to avoid infinite respawning", applet,
|
||||
respawn_delay * respawn_max);
|
||||
}
|
||||
if (retry)
|
||||
parse_schedule(applet, retry, sig);
|
||||
else
|
||||
parse_schedule(applet, NULL, sig);
|
||||
}
|
||||
|
||||
/* Expand ~ */
|
||||
@@ -673,14 +658,20 @@ int main(int argc, char **argv)
|
||||
*exec_file ? exec_file : exec);
|
||||
|
||||
if (stop) {
|
||||
pid = get_pid(pidfile);
|
||||
if (pid == -1)
|
||||
i = pid;
|
||||
else
|
||||
pid = get_pid(applet, pidfile);
|
||||
if (pid != -1) {
|
||||
i = kill(pid, SIGTERM);
|
||||
if (i != 0)
|
||||
/* We failed to stop something */
|
||||
exit(EXIT_FAILURE);
|
||||
if (i != 0)
|
||||
/* We failed to send the signal */
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
/* wait for the supervisor to go down */
|
||||
while (kill(pid, 0) == 0) {
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1;
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Even if we have not actually killed anything, we should
|
||||
* remove information about it as it may have unexpectedly
|
||||
@@ -697,7 +688,7 @@ int main(int argc, char **argv)
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
pid = get_pid(pidfile);
|
||||
pid = get_pid(applet, pidfile);
|
||||
if (pid != -1)
|
||||
if (kill(pid, 0) == 0)
|
||||
eerrorx("%s: %s is already running", applet, exec);
|
||||
@@ -736,6 +727,8 @@ int main(int argc, char **argv)
|
||||
if (child_pid != 0) {
|
||||
/* this is the supervisor */
|
||||
umask(numask);
|
||||
openlog(applet, LOG_PID, LOG_DAEMON);
|
||||
signal_setup(SIGTERM, handle_signal);
|
||||
|
||||
fp = fopen(pidfile, "w");
|
||||
if (! fp)
|
||||
@@ -760,8 +753,12 @@ int main(int argc, char **argv)
|
||||
while (!exiting) {
|
||||
wait(&i);
|
||||
if (exiting) {
|
||||
signal_setup(SIGCHLD, SIG_IGN);
|
||||
syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
|
||||
kill(child_pid, SIGTERM);
|
||||
nkilled = run_stop_schedule(applet, exec, NULL, child_pid,
|
||||
0, false, false, true);
|
||||
if (nkilled > 0)
|
||||
syslog(LOG_INFO, "killed %d processes", nkilled);
|
||||
} else {
|
||||
sleep(respawn_delay);
|
||||
if (respawn_max > 0 && respawn_period > 0) {
|
||||
|
||||
Reference in New Issue
Block a user