diff --git a/src/adverb.c b/src/adverb.c
index 13047fae51a889820f1765bfcf1dd9ce045d698f..815559af0ca7ebb956550faafdab901e3c88591a 100644
--- a/src/adverb.c
+++ b/src/adverb.c
@@ -55,6 +55,7 @@ static gboolean opt_verbose = FALSE;
 static gboolean opt_version = FALSE;
 static gboolean opt_wait = FALSE;
 static gboolean opt_write = FALSE;
+static GPid child_pid;
 
 typedef struct
 {
@@ -70,6 +71,16 @@ child_setup_cb (gpointer user_data)
   const int *iter;
   int i;
 
+  /* The adverb should wait for its child before it exits, but if it
+   * gets terminated prematurely, we want the child to terminate too.
+   * The child could reset this, but we assume it usually won't.
+   * This makes it exit even if we are killed by SIGKILL, unless it
+   * takes steps not to be. */
+  if (opt_exit_with_parent
+      && prctl (PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) != 0)
+    pv_async_signal_safe_error ("Failed to set up parent-death signal\n",
+                                LAUNCH_EX_FAILED);
+
   /* Unblock all signals */
   sigemptyset (&set);
   if (pthread_sigmask (SIG_SETMASK, &set, NULL) == -1)
@@ -328,6 +339,23 @@ generate_locales (gchar **locpath_out,
   return TRUE;
 }
 
+/* Only do async-signal-safe things here: see signal-safety(7) */
+static void
+terminate_child_cb (int signum)
+{
+  if (child_pid != 0)
+    {
+      /* pass it on to the child we're going to wait for */
+      kill (child_pid, signum);
+    }
+  else
+    {
+      /* guess I'll just die, then */
+      signal (signum, SIG_DFL);
+      raise (signum);
+    }
+}
+
 static GOptionEntry options[] =
 {
   { "fd", '\0',
@@ -442,13 +470,13 @@ main (int argc,
   GError **error = &local_error;
   int ret = EX_USAGE;
   char **command_and_args;
-  GPid child_pid;
   int wait_status = -1;
   g_autofree gchar *locales_temp_dir = NULL;
   g_auto(GStrv) my_environ = NULL;
   g_autoptr(FILE) original_stdout = NULL;
   ChildSetupData child_setup_data = { -1, NULL };
   sigset_t mask;
+  struct sigaction terminate_child_action = {};
 
   sigemptyset (&mask);
   sigaddset (&mask, SIGCHLD);
@@ -579,6 +607,16 @@ main (int argc,
         }
     }
 
+  /* Respond to common termination signals by killing the child instead of
+   * ourselves */
+  terminate_child_action.sa_handler = terminate_child_cb;
+  sigaction (SIGHUP, &terminate_child_action, NULL);
+  sigaction (SIGINT, &terminate_child_action, NULL);
+  sigaction (SIGQUIT, &terminate_child_action, NULL);
+  sigaction (SIGTERM, &terminate_child_action, NULL);
+  sigaction (SIGUSR1, &terminate_child_action, NULL);
+  sigaction (SIGUSR2, &terminate_child_action, NULL);
+
   g_debug ("Launching child process...");
   fflush (stdout);
   child_setup_data.original_stdout_fd = fileno (original_stdout);
@@ -617,6 +655,8 @@ main (int argc,
   if (!pv_wait_for_child_processes (child_pid, &wait_status, error))
     goto out;
 
+  child_pid = 0;
+
   if (WIFEXITED (wait_status))
     {
       ret = WEXITSTATUS (wait_status);