/* This file is part of TALER Copyright (C) 2014--2020 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with TALER; see the file COPYING. If not, see */ /** * @file taler-exchange-httpd_loop.c * @brief management of our main loop * @author Florian Dold * @author Benedikt Mueller * @author Christian Grothoff */ #include "platform.h" #include #include "taler-exchange-httpd_loop.h" /* ************************* Signal logic ************************** */ /** * Pipe used for signaling reloading of our key state. */ static int reload_pipe[2] = { -1, -1 }; /** * Handle a signal, writing relevant signal numbers to the pipe. * * @param signal_number the signal number */ static void handle_signal (int signal_number) { char c = (char) signal_number; /* never seen a signal_number > 127 on any platform */ (void) ! write (reload_pipe[1], &c, 1); /* While one might like to "handle errors" here, even logging via fprintf() isn't safe inside of a signal handler. So there is nothing we safely CAN do. OTOH, also very little that can go wrong in practice. Calling _exit() on errors might be a possibility, but that might do more harm than good. */// } /** * Call #handle_signal() to pass the received signal via * the control pipe. */ static void handle_sigint (void) { handle_signal (SIGINT); } /** * Call #handle_signal() to pass the received signal via * the control pipe. */ static void handle_sigterm (void) { handle_signal (SIGTERM); } /** * Call #handle_signal() to pass the received signal via * the control pipe. */ static void handle_sighup (void) { handle_signal (SIGHUP); } /** * Call #handle_signal() to pass the received signal via * the control pipe. */ static void handle_sigchld (void) { handle_signal (SIGCHLD); } int TEH_loop_run (void) { int ret; ret = 2; while (2 == ret) { char c; ssize_t res; errno = 0; res = read (reload_pipe[0], &c, 1); if ((res < 0) && (EINTR != errno)) { GNUNET_break (0); ret = GNUNET_SYSERR; break; } if (EINTR == errno) continue; switch (c) { case SIGTERM: case SIGINT: /* terminate */ ret = GNUNET_OK; break; case SIGHUP: /* restart updated binary */ ret = GNUNET_NO; break; #if HAVE_DEVELOPER case SIGCHLD: /* running in test-mode, test finished, terminate */ ret = GNUNET_OK; break; #endif default: /* unexpected character */ GNUNET_break (0); break; } } return ret; } static struct GNUNET_SIGNAL_Context *sigterm; static struct GNUNET_SIGNAL_Context *sigint; static struct GNUNET_SIGNAL_Context *sighup; static struct GNUNET_SIGNAL_Context *sigchld; int TEH_loop_init (void) { if (0 != pipe (reload_pipe)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "pipe"); return GNUNET_SYSERR; } sigterm = GNUNET_SIGNAL_handler_install (SIGTERM, &handle_sigterm); sigint = GNUNET_SIGNAL_handler_install (SIGINT, &handle_sigint); sighup = GNUNET_SIGNAL_handler_install (SIGHUP, &handle_sighup); sigchld = GNUNET_SIGNAL_handler_install (SIGCHLD, &handle_sigchld); return GNUNET_OK; } void TEH_loop_done (void) { if (NULL != sigterm) { GNUNET_SIGNAL_handler_uninstall (sigterm); sigterm = NULL; } if (NULL != sigint) { GNUNET_SIGNAL_handler_uninstall (sigint); sigint = NULL; } if (NULL != sighup) { GNUNET_SIGNAL_handler_uninstall (sighup); sighup = NULL; } if (NULL != sigchld) { GNUNET_SIGNAL_handler_uninstall (sigchld); sigchld = NULL; } if (-1 != reload_pipe[0]) { GNUNET_break (0 == close (reload_pipe[0])); GNUNET_break (0 == close (reload_pipe[1])); reload_pipe[0] = reload_pipe[1] = -1; } } /* end of taler-exchange-httpd_loop.c */