summaryrefslogtreecommitdiff
path: root/src/os_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/os_unix.c')
-rw-r--r--src/os_unix.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index 08e9fc8d2..373dce1c0 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -903,6 +903,13 @@ deathtrap SIGDEFARG(sigarg)
}
#endif
+#ifdef SIGHASARG
+ /* When SIGHUP is blocked: postpone its effect and return here. This
+ * avoids that a non-reentrant function is interrupted, e.g., free(). */
+ if (entered == 0 && sigarg == SIGHUP && !handle_sighup(SIGHUP_RCV))
+ SIGRETURN;
+#endif
+
/* Remember how often we have been called. */
++entered;
@@ -1174,6 +1181,39 @@ catch_signals(func_deadly, func_other)
}
/*
+ * Handling of SIGHUP:
+ * "when" == SIGHUP_RCV: when busy, postpone, otherwise return TRUE
+ * "when" == SIGHUP_BLOCK: Going to be busy, block SIGHUP
+ * "when" == SIGHUP_UNBLOCK: Going wait, unblock SIGHUP
+ * Returns TRUE when Vim should exit.
+ */
+ int
+handle_sighup(when)
+ int when;
+{
+ static int got_sighup = FALSE;
+ static int blocked = FALSE;
+
+ switch (when)
+ {
+ case SIGHUP_RCV: if (!blocked)
+ return TRUE; /* exit! */
+ got_sighup = TRUE;
+ got_int = TRUE; /* break any loops */
+ break;
+
+ case SIGHUP_BLOCK: blocked = TRUE;
+ break;
+
+ case SIGHUP_UNBLOCK: blocked = FALSE;
+ if (got_sighup)
+ kill(getpid(), SIGHUP);
+ break;
+ }
+ return FALSE;
+}
+
+/*
* Check_win checks whether we have an interactive stdout.
*/
/* ARGSUSED */