mirror of
https://github.com/irssi/irssi.git
synced 2026-08-23 02:22:36 +02:00
Use a pipe for the signal_handler.
Makes irssi close cleanly at box shutdown or if pkill'ed. I've been using this patch for years, I assume it's off the ML but I can't find the post now.
This commit is contained in:
parent
5ca9287182
commit
70c160d26d
1 changed files with 84 additions and 8 deletions
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
#include "network.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "levels.h"
|
#include "levels.h"
|
||||||
|
|
@ -31,6 +32,12 @@
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# define g_io_channel_new(handle) g_io_channel_win32_new_stream_socket(handle)
|
||||||
|
#else
|
||||||
|
# define g_io_channel_new(handle) g_io_channel_unix_new(handle)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SETTINGS_AUTOSAVE_TIMEOUT (1000*60*60) /* 1 hour */
|
#define SETTINGS_AUTOSAVE_TIMEOUT (1000*60*60) /* 1 hour */
|
||||||
|
|
||||||
CONFIG_REC *mainconfig;
|
CONFIG_REC *mainconfig;
|
||||||
|
|
@ -48,6 +55,10 @@ static time_t config_last_mtime;
|
||||||
static long config_last_size;
|
static long config_last_size;
|
||||||
static unsigned int config_last_checksum;
|
static unsigned int config_last_checksum;
|
||||||
|
|
||||||
|
static int signal_wakeup_pipe[2] = { -1, -1 };
|
||||||
|
static GIOChannel *signal_wakeup_read_channel;
|
||||||
|
static guint signal_wakeup_event_tag;
|
||||||
|
|
||||||
static SETTINGS_REC *settings_get(const char *key, SettingType type)
|
static SETTINGS_REC *settings_get(const char *key, SettingType type)
|
||||||
{
|
{
|
||||||
SETTINGS_REC *rec;
|
SETTINGS_REC *rec;
|
||||||
|
|
@ -570,16 +581,29 @@ GSList *settings_get_sorted(void)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sig_term(int n)
|
void signal_handler(int signal)
|
||||||
{
|
{
|
||||||
/* if we get SIGTERM after this, just die instead of coming back here. */
|
gchar signalNo = (gchar) signal;
|
||||||
signal(SIGTERM, SIG_DFL);
|
// write failures silently ignored
|
||||||
|
write(signal_wakeup_pipe[1], &signalNo, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* quit from all servers too.. */
|
void signal_wakeup_pipe_handler(void *data, GIOChannel *source, int condition) {
|
||||||
signal_emit("command quit", 1, "");
|
gchar signalNo;
|
||||||
|
gsize r;
|
||||||
|
GIOStatus status;
|
||||||
|
|
||||||
/* and die */
|
status = g_io_channel_read_chars(signal_wakeup_read_channel, &signalNo, 1, &r, NULL);
|
||||||
raise(SIGTERM);
|
if (status != G_IO_STATUS_NORMAL || r < 1) {
|
||||||
|
// ignore error conditions
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (signalNo) {
|
||||||
|
case SIGTERM:
|
||||||
|
/* Act as if the user typed "/quit" in the client */
|
||||||
|
signal_emit("command quit", 1, "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Yes, this is my own stupid checksum generator, some "real" algorithm
|
/* Yes, this is my own stupid checksum generator, some "real" algorithm
|
||||||
|
|
@ -675,10 +699,20 @@ static CONFIG_REC *parse_configfile(const char *fname)
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_nonblock_flag (int fd)
|
||||||
|
{
|
||||||
|
int flags = fcntl (fd, F_GETFL, 0);
|
||||||
|
if (flags == -1)
|
||||||
|
return -1;
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
return fcntl (fd, F_SETFL, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static void init_configfile(void)
|
static void init_configfile(void)
|
||||||
{
|
{
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
char *str;
|
char *str;
|
||||||
|
struct sigaction act;
|
||||||
|
|
||||||
if (stat(get_irssi_dir(), &statbuf) != 0) {
|
if (stat(get_irssi_dir(), &statbuf) != 0) {
|
||||||
/* ~/.irssi not found, create it. */
|
/* ~/.irssi not found, create it. */
|
||||||
|
|
@ -702,9 +736,49 @@ static void init_configfile(void)
|
||||||
g_free(str);
|
g_free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGTERM, sig_term);
|
if (pipe(signal_wakeup_pipe)) {
|
||||||
|
g_warning("Failed to create signal wakeup pipe - SIGTERM not attached");
|
||||||
|
signal_wakeup_pipe[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (set_nonblock_flag(signal_wakeup_pipe[0]) || set_nonblock_flag(signal_wakeup_pipe[1])) {
|
||||||
|
g_warning("Failed to configure signal wakeup pipe - SIGTERM not attached");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
signal_wakeup_read_channel = g_io_channel_new(signal_wakeup_pipe[0]);
|
||||||
|
signal_wakeup_event_tag = g_input_add(signal_wakeup_read_channel, G_INPUT_READ, signal_wakeup_pipe_handler, NULL);
|
||||||
|
|
||||||
|
sigemptyset (&act.sa_mask);
|
||||||
|
act.sa_flags = SA_RESETHAND;
|
||||||
|
act.sa_handler = signal_handler;
|
||||||
|
sigaction(SIGTERM, &act, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void deinit_configfile(void)
|
||||||
|
{
|
||||||
|
struct sigaction act;
|
||||||
|
|
||||||
|
sigemptyset (&act.sa_mask);
|
||||||
|
act.sa_flags = 0;
|
||||||
|
act.sa_handler = SIG_DFL;
|
||||||
|
sigaction(SIGTERM, &act, NULL);
|
||||||
|
|
||||||
|
if (signal_wakeup_event_tag) {
|
||||||
|
g_source_remove(signal_wakeup_event_tag);
|
||||||
|
}
|
||||||
|
if (signal_wakeup_read_channel) {
|
||||||
|
g_io_channel_shutdown(signal_wakeup_read_channel, FALSE, NULL);
|
||||||
|
g_io_channel_unref(signal_wakeup_read_channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signal_wakeup_pipe[0]) {
|
||||||
|
close(signal_wakeup_pipe[0]);
|
||||||
|
close(signal_wakeup_pipe[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int settings_reread(const char *fname)
|
int settings_reread(const char *fname)
|
||||||
{
|
{
|
||||||
CONFIG_REC *tempconfig;
|
CONFIG_REC *tempconfig;
|
||||||
|
|
@ -818,6 +892,8 @@ void settings_deinit(void)
|
||||||
signal_remove("irssi init finished", (SIGNAL_FUNC) sig_init_finished);
|
signal_remove("irssi init finished", (SIGNAL_FUNC) sig_init_finished);
|
||||||
signal_remove("gui exit", (SIGNAL_FUNC) sig_autosave);
|
signal_remove("gui exit", (SIGNAL_FUNC) sig_autosave);
|
||||||
|
|
||||||
|
deinit_configfile();
|
||||||
|
|
||||||
g_slist_foreach(last_invalid_modules, (GFunc) g_free, NULL);
|
g_slist_foreach(last_invalid_modules, (GFunc) g_free, NULL);
|
||||||
g_slist_free(last_invalid_modules);
|
g_slist_free(last_invalid_modules);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue