From a0f6932ebe21ff6908db250019bdb46f7b0dfedc Mon Sep 17 00:00:00 2001
From: Max Kellermann <max.kellermann@gmail.com>
Date: Mon, 6 Mar 2023 12:53:19 +0100
Subject: [PATCH] unix/SignalHandlers: shut down if parent process dies in
 --no-daemon mode

By default, if the parent of a process dies, the process gets SIGHUP
and is supposed to shut down.  This however doesn't work for MPD,
because MPD redefines SIGHUP with a different meaning (like most
daemons do).

To work around this, we configure the kernel to send SIGTERM instead
of SIGHUP.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1706
---
 NEWS                        |  2 ++
 src/Main.cxx                |  5 ++++-
 src/unix/SignalHandlers.cxx | 14 +++++++++++++-
 src/unix/SignalHandlers.hxx |  6 +++---
 4 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/NEWS b/NEWS
index 23e59ede8..5cb84ea24 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ ver 0.23.13 (not yet released)
   - curl: fix busy loop after connection failed
 * output
   - pipewire: fix corruption bug due to missing lock
+* Linux
+  - shut down if parent process dies in --no-daemon mode
 
 ver 0.23.12 (2023/01/17)
 * input
diff --git a/src/Main.cxx b/src/Main.cxx
index bcbda0bb5..6b9bdf641 100644
--- a/src/Main.cxx
+++ b/src/Main.cxx
@@ -482,7 +482,10 @@ MainConfigured(const CommandLineOptions &options,
 #ifndef ANDROID
 	setup_log_output();
 
-	const ScopeSignalHandlersInit signal_handlers_init(instance);
+	const ScopeSignalHandlersInit signal_handlers_init{
+		instance,
+		options.daemon,
+	};
 #endif
 
 	instance.io_thread.Start();
diff --git a/src/unix/SignalHandlers.cxx b/src/unix/SignalHandlers.cxx
index 886dc78d5..e58dda7de 100644
--- a/src/unix/SignalHandlers.cxx
+++ b/src/unix/SignalHandlers.cxx
@@ -30,6 +30,10 @@
 
 #include <csignal>
 
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
+
 static constexpr Domain signal_handlers_domain("signal_handlers");
 
 static void
@@ -60,7 +64,7 @@ handle_reload_event(void *ctx) noexcept
 #endif
 
 void
-SignalHandlersInit(Instance &instance)
+SignalHandlersInit(Instance &instance, bool daemon)
 {
 	auto &loop = instance.event_loop;
 
@@ -79,6 +83,14 @@ SignalHandlersInit(Instance &instance)
 
 	SignalMonitorRegister(SIGHUP, {&instance, handle_reload_event});
 #endif
+
+	if (!daemon) {
+#ifdef __linux__
+		/* if MPD was not daemonized, shut it down when the
+		   parent process dies */
+		prctl(PR_SET_PDEATHSIG, SIGTERM);
+#endif
+	}
 }
 
 void
diff --git a/src/unix/SignalHandlers.hxx b/src/unix/SignalHandlers.hxx
index dbcec12d6..1eb9a305d 100644
--- a/src/unix/SignalHandlers.hxx
+++ b/src/unix/SignalHandlers.hxx
@@ -23,15 +23,15 @@
 struct Instance;
 
 void
-SignalHandlersInit(Instance &instance);
+SignalHandlersInit(Instance &instance, bool daemon);
 
 void
 SignalHandlersFinish() noexcept;
 
 class ScopeSignalHandlersInit {
 public:
-	ScopeSignalHandlersInit(Instance &instance) {
-		SignalHandlersInit(instance);
+	ScopeSignalHandlersInit(Instance &instance, bool daemon) {
+		SignalHandlersInit(instance, daemon);
 	}
 
 	~ScopeSignalHandlersInit() noexcept {