From 86e7e876d96eccdf132a17f5ab3d8aa74179476f Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Thu, 23 Jun 2022 06:12:17 +0300 Subject: [PATCH 52/52] Move server signal handling to a new srv_signal.[ch] module See osdn #44914 Signed-off-by: Marko Lindqvist --- meson.build | 1 + server/Makefile.am | 2 + server/civserver.c | 101 +------------------------------- server/srv_signal.c | 140 ++++++++++++++++++++++++++++++++++++++++++++ server/srv_signal.h | 18 ++++++ 5 files changed, 164 insertions(+), 98 deletions(-) create mode 100644 server/srv_signal.c create mode 100644 server/srv_signal.h diff --git a/meson.build b/meson.build index d664d65162..d868ce3881 100644 --- a/meson.build +++ b/meson.build @@ -909,6 +909,7 @@ server_lib = static_library('fc_server', 'server/spacerace.c', 'server/srv_log.c', 'server/srv_main.c', + 'server/srv_signal.c', 'server/stdinhand.c', 'server/techtools.c', 'server/unithand.c', diff --git a/server/Makefile.am b/server/Makefile.am index b59b4ef95e..ed29c9ff04 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -110,6 +110,8 @@ libfreeciv_srv_la_SOURCES = \ srv_log.h \ srv_main.c \ srv_main.h \ + srv_signal.c \ + srv_signal.h \ stdinhand.c \ stdinhand.h \ techtools.h \ diff --git a/server/civserver.c b/server/civserver.c index 30b0d19e34..a77eec0c6d 100644 --- a/server/civserver.c +++ b/server/civserver.c @@ -45,7 +45,6 @@ #include "fcintl.h" #include "log.h" #include "support.h" -#include "timing.h" /* common */ #include "capstr.h" @@ -59,78 +58,14 @@ #include "meta.h" #include "sernet.h" #include "srv_main.h" +#include "srv_signal.h" #ifdef GENERATING_MAC static void Mac_options(int argc); /* don't need argv */ #endif -#ifdef HAVE_SIGNAL_H -# define USE_INTERRUPT_HANDLERS -#endif - -#ifdef USE_INTERRUPT_HANDLERS -#define save_and_exit(sig) \ -if (S_S_RUNNING == server_state()) { \ - save_game_auto(#sig, AS_INTERRUPT); \ -} \ -exit(EXIT_SUCCESS); - /**********************************************************************//** - This function is called when a SIGINT (ctrl-c) is received. It will exit - only if two SIGINTs are received within a second. -**************************************************************************/ -static void signal_handler(int sig) -{ - static struct timer *timer = NULL; - - switch (sig) { - case SIGINT: - if (timer && timer_read_seconds(timer) <= 1.0) { - save_and_exit(SIGINT); - } else { - if (game.info.timeout == -1) { - log_normal(_("Setting timeout to 0. Autogame will stop.")); - game.info.timeout = 0; - } - if (!timer) { - log_normal(_("You must interrupt Freeciv twice " - "within one second to make it exit.")); - } - } - timer = timer_renew(timer, TIMER_USER, TIMER_ACTIVE, - timer != NULL ? NULL : "ctrlc"); - timer_start(timer); - break; - -#ifdef SIGHUP - case SIGHUP: - save_and_exit(SIGHUP); - break; -#endif /* SIGHUP */ - - case SIGTERM: - save_and_exit(SIGTERM); - break; - -#ifdef SIGPIPE - case SIGPIPE: - if (signal(SIGPIPE, signal_handler) == SIG_ERR) { - /* Because the signal may have interrupted arbitrary code, we use - * fprintf() and _exit() here instead of log_*() and exit() so - * that we don't accidentally call any "unsafe" functions here - * (see the manual page for the signal function). */ - fprintf(stderr, "\nFailed to reset SIGPIPE handler " - "while handling SIGPIPE.\n"); - _exit(EXIT_FAILURE); - } - break; -#endif /* SIGPIPE */ - } -} -#endif /* USE_INTERRUPT_HANDLERS */ - -/**********************************************************************//** - Entry point for Freeciv server. Basically, does two things: + Entry point for Freeciv server. Basically, does two things: 1. Parses command-line arguments (possibly dialog, on mac). 2. Calls the main server-loop routine. **************************************************************************/ @@ -152,37 +87,7 @@ int main(int argc, char *argv[]) # endif /* FREECIV_NDEBUG */ #endif /* FREECIV_MSWINDOWS */ -#ifdef USE_INTERRUPT_HANDLERS - if (SIG_ERR == signal(SIGINT, signal_handler)) { - fc_fprintf(stderr, _("Failed to install SIGINT handler: %s\n"), - fc_strerror(fc_get_errno())); - exit(EXIT_FAILURE); - } - -#ifdef SIGHUP - if (SIG_ERR == signal(SIGHUP, signal_handler)) { - fc_fprintf(stderr, _("Failed to install SIGHUP handler: %s\n"), - fc_strerror(fc_get_errno())); - exit(EXIT_FAILURE); - } -#endif /* SIGHUP */ - - if (SIG_ERR == signal(SIGTERM, signal_handler)) { - fc_fprintf(stderr, _("Failed to install SIGTERM handler: %s\n"), - fc_strerror(fc_get_errno())); - exit(EXIT_FAILURE); - } - -#ifdef SIGPIPE - /* Ignore SIGPIPE, the error is handled by the return value - * of the write call. */ - if (SIG_ERR == signal(SIGPIPE, signal_handler)) { - fc_fprintf(stderr, _("Failed to ignore SIGPIPE: %s\n"), - fc_strerror(fc_get_errno())); - exit(EXIT_FAILURE); - } -#endif /* SIGPIPE */ -#endif /* USE_INTERRUPT_HANDLERS */ + setup_interrupt_handlers(); /* initialize server */ srv_init(); diff --git a/server/srv_signal.c b/server/srv_signal.c new file mode 100644 index 0000000000..c86a5d0c87 --- /dev/null +++ b/server/srv_signal.c @@ -0,0 +1,140 @@ +/*********************************************************************** + Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "fc_prehdrs.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SIGNAL_H +#include +#endif + +/* utility */ +#include "fciconv.h" +#include "log.h" +#include "timing.h" + +/* server */ +#include "srv_main.h" + +#include "srv_signal.h" + +#ifdef HAVE_SIGNAL_H +#define USE_INTERRUPT_HANDLERS +#endif + +#ifdef USE_INTERRUPT_HANDLERS +#define save_and_exit(sig) \ +if (S_S_RUNNING == server_state()) { \ + save_game_auto(#sig, AS_INTERRUPT); \ +} \ +exit(EXIT_SUCCESS); + +/**********************************************************************//** + This function is called when a SIGINT (ctrl-c) is received. It will exit + only if two SIGINTs are received within a second. +**************************************************************************/ +static void signal_handler(int sig) +{ + static struct timer *timer = NULL; + + switch (sig) { + case SIGINT: + if (timer && timer_read_seconds(timer) <= 1.0) { + save_and_exit(SIGINT); + } else { + if (game.info.timeout == -1) { + log_normal(_("Setting timeout to 0. Autogame will stop.")); + game.info.timeout = 0; + } + if (!timer) { + log_normal(_("You must interrupt Freeciv twice " + "within one second to make it exit.")); + } + } + timer = timer_renew(timer, TIMER_USER, TIMER_ACTIVE, + timer != NULL ? NULL : "ctrlc"); + timer_start(timer); + break; + +#ifdef SIGHUP + case SIGHUP: + save_and_exit(SIGHUP); + break; +#endif /* SIGHUP */ + + case SIGTERM: + save_and_exit(SIGTERM); + break; + +#ifdef SIGPIPE + case SIGPIPE: + if (signal(SIGPIPE, signal_handler) == SIG_ERR) { + /* Because the signal may have interrupted arbitrary code, we use + * fprintf() and _exit() here instead of log_*() and exit() so + * that we don't accidentally call any "unsafe" functions here + * (see the manual page for the signal function). */ + fprintf(stderr, "\nFailed to reset SIGPIPE handler " + "while handling SIGPIPE.\n"); + _exit(EXIT_FAILURE); + } + break; +#endif /* SIGPIPE */ + } +} + +#endif /* USE_INTERRUPT_HANDLERS */ + +/**********************************************************************//** + Sets interrupt handlers for the server. +**************************************************************************/ +void setup_interrupt_handlers(void) +{ +#ifdef USE_INTERRUPT_HANDLERS + if (SIG_ERR == signal(SIGINT, signal_handler)) { + fc_fprintf(stderr, _("Failed to install SIGINT handler: %s\n"), + fc_strerror(fc_get_errno())); + exit(EXIT_FAILURE); + } + +#ifdef SIGHUP + if (SIG_ERR == signal(SIGHUP, signal_handler)) { + fc_fprintf(stderr, _("Failed to install SIGHUP handler: %s\n"), + fc_strerror(fc_get_errno())); + exit(EXIT_FAILURE); + } +#endif /* SIGHUP */ + + if (SIG_ERR == signal(SIGTERM, signal_handler)) { + fc_fprintf(stderr, _("Failed to install SIGTERM handler: %s\n"), + fc_strerror(fc_get_errno())); + exit(EXIT_FAILURE); + } + +#ifdef SIGPIPE + /* Ignore SIGPIPE, the error is handled by the return value + * of the write call. */ + if (SIG_ERR == signal(SIGPIPE, signal_handler)) { + fc_fprintf(stderr, _("Failed to ignore SIGPIPE: %s\n"), + fc_strerror(fc_get_errno())); + exit(EXIT_FAILURE); + } +#endif /* SIGPIPE */ +#endif /* USE_INTERRUPT_HANDLERS */ +} diff --git a/server/srv_signal.h b/server/srv_signal.h new file mode 100644 index 0000000000..428063f971 --- /dev/null +++ b/server/srv_signal.h @@ -0,0 +1,18 @@ +/*********************************************************************** + Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +***********************************************************************/ +#ifndef FC__SRV_SIGNAL_H +#define FC__SRV_SIGNAL_H + +void setup_interrupt_handlers(void); + +#endif /* FC__SRV_SIGNAL_H */ -- 2.35.1