Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ int notify_users_at = 0; /* Minutes past the hour to notify users of notes? */
char version[128]; /* Version info (long form) */
char ver[41]; /* Version info (short form) */

volatile sig_atomic_t do_restart = 0; /* .restart has been called, restart ASAP */
int resolve_timeout = RES_TIMEOUT; /* Hostname/address lookup timeout */
char quit_msg[1024]; /* Quit message */
volatile sig_atomic_t do_restart = 0; /* .restart has been called, restart ASAP */
static volatile sig_atomic_t do_die = 0; /* SIGTERM/SIGINT received, die ASAP */
int resolve_timeout = RES_TIMEOUT; /* Hostname/address lookup timeout */
char quit_msg[1024]; /* Quit message */

/* Moved here for n flag warning, put back in do_arg if removed */
unsigned char cliflags = 0;
Expand Down Expand Up @@ -365,12 +366,18 @@ static void got_fpe(int z)

static void got_term(int z)
{
/* Now we die by default on sigterm, but scripts have the chance to
* catch the event themselves and cancel shutdown by returning 1
/* Shutting down mid-mainloop from a signal handler is not safe (the
* signal can arrive while the heap or the user list is in an
* inconsistent state), so just flag it and let mainloop() do the work.
*/
if (check_tcl_signal("sigterm"))
return;
kill_bot("ACK, I've been terminated!", "TERMINATE SIGNAL -- SIGNING OFF");
if (do_die) {
/* Second signal while the first is still pending or shutdown is
* already in progress: the bot is probably hung, so die immediately
* without cleanup.
*/
_exit(1);
}
do_die = 1;
}

static void got_quit(int z)
Expand Down Expand Up @@ -730,6 +737,20 @@ static void mainloop(int toplevel)
*/
now = time(NULL);

/* SIGTERM or SIGINT was received. We die by default, but scripts have
* the chance to catch the event themselves and cancel shutdown by
* returning 1.
*/
if (do_die) {
/* Leave do_die set while shutting down, so a repeated signal still
* forces an immediate exit if the sigterm bind or the cleanup hangs.
*/
if (check_tcl_signal("sigterm"))
do_die = 0;
else
kill_bot("ACK, I've been terminated!", "TERMINATE SIGNAL -- SIGNING OFF");
}

/* If we want to restart, we have to unwind to the toplevel.
* Tcl will Panic if we kill the interp with Tcl_Eval in progress.
* This is done by returning -1 in tickle_WaitForEvent.
Expand Down
Loading