summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/killall.c22
-rw-r--r--src/core/killall.h2
-rw-r--r--src/core/main.c2
-rw-r--r--src/core/shutdown.c4
-rw-r--r--src/shared/util.c12
5 files changed, 28 insertions, 14 deletions
diff --git a/src/core/killall.c b/src/core/killall.c
index e395050107..a7828dc047 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -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");
diff --git a/src/core/killall.h b/src/core/killall.h
index 95b110fae1..bdb73e44be 100644
--- a/src/core/killall.h
+++ b/src/core/killall.h
@@ -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);
diff --git a/src/core/main.c b/src/core/main.c
index bc92f65fd6..dbc98db84a 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -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);
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index bcf2eecf33..31129b7697 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -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;
diff --git a/src/shared/util.c b/src/shared/util.c
index 97c9497df6..3a4d1965ae 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -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;
}