shutdown: during final killing spree also send SIGHUP in addition to SIGTERM to deal with shells

This makes shutdown a bit faster if debug-shell.service is enabled.
This commit is contained in:
Lennart Poettering 2013-11-25 18:08:02 +01:00
parent 26fefda707
commit 0bee65f062
6 changed files with 30 additions and 14 deletions

2
TODO
View File

@ -43,6 +43,8 @@ CGroup Rework Completion:
Features:
* general: get rid of readdir_r/dirent_storage stuff, it's unnecessary on Linux
* add API to clone sd_bus_message objects
* sd-bus: synthesized messages should get serial number (uint32_t) -1

View File

@ -145,7 +145,7 @@ static void wait_for_children(Set *pids, sigset_t *mask) {
}
}
static int killall(int sig, Set *pids) {
static int killall(int sig, Set *pids, bool send_sighup) {
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *d;
@ -178,12 +178,28 @@ static int killall(int sig, Set *pids) {
set_put(pids, ULONG_TO_PTR((unsigned long) pid));
} else if (errno != ENOENT)
log_warning("Could not kill %d: %m", pid);
if (send_sighup) {
/* Optionally, also send a SIGHUP signal, but
only if the process has a controlling
tty. This is useful to allow handling of
shells which ignore SIGTERM but react to
SIGHUP. We do not send this to processes that
have no controlling TTY since we don't want to
trigger reloads of daemon processes. Also we
make sure to only send this after SIGTERM so
that SIGTERM is always first in the queue. */
if (get_ctty_devnr(pid, NULL) >= 0)
kill(pid, SIGHUP);
}
}
return set_size(pids);
}
void broadcast_signal(int sig, bool wait_for_exit) {
void broadcast_signal(int sig, bool send_sighup, bool wait_for_exit) {
sigset_t mask, oldmask;
Set *pids = NULL;
@ -197,7 +213,7 @@ void broadcast_signal(int sig, bool wait_for_exit) {
if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
log_warning("kill(-1, SIGSTOP) failed: %m");
killall(sig, pids);
killall(sig, pids, send_sighup);
if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
log_warning("kill(-1, SIGCONT) failed: %m");

View File

@ -21,4 +21,4 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
void broadcast_signal(int sig, bool wait);
void broadcast_signal(int sig, bool wait, bool send_sighup);

View File

@ -1745,7 +1745,7 @@ finish:
* initrd, but don't wait for them, so that we
* can handle the SIGCHLD for them after
* deserializing. */
broadcast_signal(SIGTERM, false);
broadcast_signal(SIGTERM, false, true);
/* And switch root */
r = switch_root(switch_root_dir);

View File

@ -195,10 +195,10 @@ int main(int argc, char *argv[]) {
mlockall(MCL_CURRENT|MCL_FUTURE);
log_info("Sending SIGTERM to remaining processes...");
broadcast_signal(SIGTERM, true);
broadcast_signal(SIGTERM, true, true);
log_info("Sending SIGKILL to remaining processes...");
broadcast_signal(SIGKILL, true);
broadcast_signal(SIGKILL, true, false);
if (in_container) {
need_swapoff = false;

View File

@ -2525,10 +2525,8 @@ int get_ctty_devnr(pid_t pid, dev_t *d) {
char line[LINE_MAX], *p;
unsigned long ttynr;
const char *fn;
int k;
assert(pid >= 0);
assert(d);
if (pid == 0)
fn = "/proc/self/stat";
@ -2539,10 +2537,8 @@ int get_ctty_devnr(pid_t pid, dev_t *d) {
if (!f)
return -errno;
if (!fgets(line, sizeof(line), f)) {
k = feof(f) ? -EIO : -errno;
return k;
}
if (!fgets(line, sizeof(line), f))
return feof(f) ? -EIO : -errno;
p = strrchr(line, ')');
if (!p)
@ -2562,7 +2558,9 @@ int get_ctty_devnr(pid_t pid, dev_t *d) {
if (major(ttynr) == 0 && minor(ttynr) == 0)
return -ENOENT;
*d = (dev_t) ttynr;
if (d)
*d = (dev_t) ttynr;
return 0;
}