degesch: better SIGTSTP handling

This commit is contained in:
Přemysl Eric Janouch 2015-11-15 15:36:03 +01:00
parent a1e47ca4c9
commit f11635ed7f

View File

@ -1371,6 +1371,7 @@ struct app_context
struct str input_buffer; ///< Buffered pasted content struct str input_buffer; ///< Buffered pasted content
bool running_backlog_helper; ///< Running a backlog helper bool running_backlog_helper; ///< Running a backlog helper
int terminal_suspended; ///< Terminal suspension level
} }
*g_ctx; *g_ctx;
@ -8984,6 +8985,10 @@ toggle_bracketed_paste (bool enable)
static void static void
suspend_terminal (struct app_context *ctx) suspend_terminal (struct app_context *ctx)
{ {
// Terminal can get suspended by both backlog helper and SIGTSTP handling
if (ctx->terminal_suspended++ > 0)
return;
#ifdef HAVE_READLINE #ifdef HAVE_READLINE
rl_deprep_terminal (); rl_deprep_terminal ();
#elif defined (HAVE_EDITLINE) #elif defined (HAVE_EDITLINE)
@ -8999,6 +9004,9 @@ suspend_terminal (struct app_context *ctx)
static void static void
resume_terminal (struct app_context *ctx) resume_terminal (struct app_context *ctx)
{ {
if (--ctx->terminal_suspended > 0)
return;
#ifdef HAVE_READLINE #ifdef HAVE_READLINE
rl_prep_terminal (true); rl_prep_terminal (true);
#elif defined (HAVE_EDITLINE) #elif defined (HAVE_EDITLINE)
@ -9760,6 +9768,9 @@ signal_superhandler (int signum)
case SIGCHLD: case SIGCHLD:
postpone_signal_handling ('c'); postpone_signal_handling ('c');
break; break;
case SIGTSTP:
postpone_signal_handling ('s');
break;
default: default:
hard_assert (!"unhandled signal"); hard_assert (!"unhandled signal");
} }
@ -9795,6 +9806,7 @@ setup_signal_handlers (void)
if (sigaction (SIGWINCH, &sa, NULL) == -1 if (sigaction (SIGWINCH, &sa, NULL) == -1
|| sigaction (SIGINT, &sa, NULL) == -1 || sigaction (SIGINT, &sa, NULL) == -1
|| sigaction (SIGTERM, &sa, NULL) == -1 || sigaction (SIGTERM, &sa, NULL) == -1
|| sigaction (SIGTSTP, &sa, NULL) == -1
|| sigaction (SIGCHLD, &sa, NULL) == -1) || sigaction (SIGCHLD, &sa, NULL) == -1)
exit_fatal ("sigaction: %s", strerror (errno)); exit_fatal ("sigaction: %s", strerror (errno));
} }
@ -9844,8 +9856,17 @@ try_reap_child (struct app_context *ctx)
static void static void
on_signal_pipe_readable (const struct pollfd *fd, struct app_context *ctx) on_signal_pipe_readable (const struct pollfd *fd, struct app_context *ctx)
{ {
char dummy; char id = 0;
(void) read (fd->fd, &dummy, 1); (void) read (fd->fd, &id, 1);
// Stop ourselves cleanly, even if it makes little sense to do this
if (id == 's')
{
suspend_terminal (ctx);
kill (getpid (), SIGSTOP);
g_winch_received = true;
resume_terminal (ctx);
}
// Reap all dead children (since the signal pipe may overflow etc. we run // Reap all dead children (since the signal pipe may overflow etc. we run
// waitpid() in a loop to return all the zombies it knows about). // waitpid() in a loop to return all the zombies it knows about).