mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 23:23:04 +01:00
shutdown fbserver when fbguard receives TERM or INT signal
This commit is contained in:
parent
c9a0da0c0e
commit
e9816e87af
@ -37,6 +37,8 @@
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#else
|
||||
int errno = -1;
|
||||
#endif
|
||||
|
||||
#include "../jrd/common.h"
|
||||
@ -57,6 +59,15 @@ const char* INTERBASE_USER = "interbase";
|
||||
const char* FIREBIRD_USER = "firebird";
|
||||
const char* INTERBASE_USER_SHORT= "interbas";
|
||||
|
||||
volatile sig_atomic_t shutting_down;
|
||||
|
||||
|
||||
void shutdown_handler(int)
|
||||
{
|
||||
shutting_down = 1;
|
||||
}
|
||||
|
||||
|
||||
int CLIB_ROUTINE main( int argc, char **argv)
|
||||
{
|
||||
/**************************************
|
||||
@ -77,6 +88,7 @@ int CLIB_ROUTINE main( int argc, char **argv)
|
||||
bool done = true;
|
||||
const TEXT* prog_name = argv[0];
|
||||
const TEXT* pidfilename = 0;
|
||||
int guard_exit_code = 0;
|
||||
|
||||
const TEXT* const* const end = argc + argv;
|
||||
argv++;
|
||||
@ -141,25 +153,43 @@ int CLIB_ROUTINE main( int argc, char **argv)
|
||||
|
||||
/* move the server name into the argument to be passed */
|
||||
TEXT process_name[1024];
|
||||
process_name[0] = '\0';
|
||||
TEXT* server_args[2];
|
||||
server_args[0] = process_name;
|
||||
server_args[1] = NULL;
|
||||
|
||||
shutting_down = 0;
|
||||
if (UTIL_set_handler(SIGTERM, shutdown_handler, false) < 0) {
|
||||
fprintf(stderr, "%s: Cannot set signal handler (error %d).\n",
|
||||
prog_name, errno);
|
||||
exit(-5);
|
||||
}
|
||||
if (UTIL_set_handler(SIGINT, shutdown_handler, false) < 0) {
|
||||
fprintf(stderr, "%s: Cannot set signal handler (error %d).\n",
|
||||
prog_name, errno);
|
||||
exit(-5);
|
||||
}
|
||||
|
||||
// detach from controlling tty
|
||||
divorce_terminal(0);
|
||||
|
||||
do {
|
||||
int ret_code;
|
||||
|
||||
if (shutting_down) {
|
||||
// don't start a child
|
||||
break;
|
||||
}
|
||||
|
||||
gds__log("%s: guardian starting %s\n",
|
||||
prog_name, SUPER_SERVER_BINARY);
|
||||
pid_t child_pid = UTIL_start_process(SUPER_SERVER_BINARY, server_args);
|
||||
if (child_pid == -1) {
|
||||
/* could not fork the server */
|
||||
gds__log("%s: guardian could not start %s\n", prog_name,
|
||||
server_args[1] ? server_args[1] : SUPER_SERVER_BINARY);
|
||||
fprintf(stderr, "%s: Could not start %s\n", prog_name,
|
||||
server_args[1] ? server_args[1] : SUPER_SERVER_BINARY);
|
||||
gds__log("%s: guardian could not start %s\n",
|
||||
prog_name, process_name);
|
||||
fprintf(stderr, "%s: Could not start %s\n",
|
||||
prog_name, process_name);
|
||||
UTIL_ex_unlock(fd_guard);
|
||||
exit(-4);
|
||||
}
|
||||
@ -172,51 +202,74 @@ int CLIB_ROUTINE main( int argc, char **argv)
|
||||
fclose(pf);
|
||||
}
|
||||
else {
|
||||
#ifndef HAVE_ERRNO_H
|
||||
int errno = -1;
|
||||
#endif
|
||||
gds__log("%s: guardian could not open %s for writing, error %d\n",
|
||||
prog_name, pidfilename, errno);
|
||||
}
|
||||
}
|
||||
|
||||
/* wait for child to die, and evaluate exit status */
|
||||
ret_code = UTIL_wait_for_child(child_pid);
|
||||
bool shutdown_child = true;
|
||||
if (!shutting_down) {
|
||||
ret_code = UTIL_wait_for_child(child_pid, shutting_down);
|
||||
shutdown_child = (ret_code == -2);
|
||||
}
|
||||
if (shutting_down) {
|
||||
if (shutdown_child) {
|
||||
ret_code = UTIL_shutdown_child(child_pid, 3, 1);
|
||||
if (ret_code < 0) {
|
||||
gds__log(
|
||||
"%s: error while shutting down %s (%d)\n",
|
||||
prog_name, process_name, errno);
|
||||
guard_exit_code = -6;
|
||||
}
|
||||
else if (ret_code == 1) {
|
||||
gds__log(
|
||||
"%s: %s killed (did not terminate)\n",
|
||||
prog_name, process_name);
|
||||
}
|
||||
else if (ret_code == 2) {
|
||||
gds__log(
|
||||
"%s: unable to shutdown %s\n",
|
||||
prog_name, process_name);
|
||||
}
|
||||
else {
|
||||
gds__log(
|
||||
"%s: %s terminated\n",
|
||||
prog_name, process_name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ret_code != NORMAL_EXIT) {
|
||||
/* check for startup error */
|
||||
if (ret_code == STARTUP_ERROR) {
|
||||
gds__log("%s: %s terminated due to startup error (%d)\n",
|
||||
prog_name, server_args[1] ? server_args[1] :
|
||||
SUPER_SERVER_BINARY, ret_code);
|
||||
prog_name, process_name, ret_code);
|
||||
if (option == IGNORE) {
|
||||
gds__log
|
||||
("%s: %s terminated due to startup error (%d)\n Trying again\n",
|
||||
prog_name,
|
||||
server_args[1] ? server_args[1] :
|
||||
SUPER_SERVER_BINARY, ret_code);
|
||||
prog_name, process_name, ret_code);
|
||||
|
||||
done = false; /* Try it again, Sam (even if it is a startup error) FSG 8.11.2000 */
|
||||
}
|
||||
else {
|
||||
gds__log("%s: %s terminated due to startup error (%d)\n",
|
||||
prog_name, server_args[1] ? server_args[1] :
|
||||
SUPER_SERVER_BINARY, ret_code);
|
||||
prog_name, process_name, ret_code);
|
||||
|
||||
done = true; /* do not restart we have a startup problem */
|
||||
}
|
||||
}
|
||||
else {
|
||||
gds__log("%s: %s terminated abnormally (%d)\n", prog_name,
|
||||
server_args[1] ? server_args[1] :
|
||||
SUPER_SERVER_BINARY, ret_code);
|
||||
gds__log("%s: %s terminated abnormally (%d)\n",
|
||||
prog_name, process_name, ret_code);
|
||||
if (option == FOREVER || option == IGNORE)
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Normal shutdown - eg: via ibmgr - don't restart the server */
|
||||
gds__log("%s: %s normal shutdown.\n", prog_name,
|
||||
server_args[1] ? server_args[1] : SUPER_SERVER_BINARY);
|
||||
gds__log("%s: %s normal shutdown.\n",
|
||||
prog_name, process_name);
|
||||
done = true;
|
||||
}
|
||||
} while (!done);
|
||||
@ -225,5 +278,5 @@ int CLIB_ROUTINE main( int argc, char **argv)
|
||||
remove(pidfilename);
|
||||
}
|
||||
UTIL_ex_unlock(fd_guard);
|
||||
exit(0);
|
||||
exit(guard_exit_code);
|
||||
} /* main */
|
||||
|
@ -120,7 +120,7 @@ pid_t UTIL_start_process(const char* process, char** argv)
|
||||
}
|
||||
|
||||
|
||||
int UTIL_wait_for_child( pid_t child_pid)
|
||||
int UTIL_wait_for_child(pid_t child_pid, const volatile sig_atomic_t& shutting_down)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -135,6 +135,7 @@ int UTIL_wait_for_child( pid_t child_pid)
|
||||
* Return code:
|
||||
* 0 Normal exit
|
||||
* -1 Abnormal exit - unknown reason.
|
||||
* -2 TERM signal caught
|
||||
* Other Abnormal exit - process error code returned.
|
||||
*
|
||||
**************************************/
|
||||
@ -145,10 +146,14 @@ int UTIL_wait_for_child( pid_t child_pid)
|
||||
/* wait for the child process with child_pid to exit */
|
||||
|
||||
while (waitpid(child_pid, &child_exit_status, 0) == -1)
|
||||
if (SYSCALL_INTERRUPTED(errno))
|
||||
continue;
|
||||
else
|
||||
if (SYSCALL_INTERRUPTED(errno)) {
|
||||
if (shutting_down)
|
||||
return -2;
|
||||
else
|
||||
continue;
|
||||
} else {
|
||||
return (errno);
|
||||
}
|
||||
|
||||
/* Check for very specific conditions before we assume the child
|
||||
did a normal exit. */
|
||||
@ -169,6 +174,65 @@ int UTIL_wait_for_child( pid_t child_pid)
|
||||
}
|
||||
|
||||
|
||||
void alrm_handler(int)
|
||||
{
|
||||
// handler for SIGALRM
|
||||
// doesn't do anything, just interrupts a syscall
|
||||
}
|
||||
|
||||
|
||||
int UTIL_shutdown_child(pid_t child_pid,
|
||||
unsigned timeout_term, unsigned timeout_kill)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* U T I L _ s h u t d o w n _ c h i l d
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
*
|
||||
* Terminates child using TERM signal, then KILL if it does not finish
|
||||
* within specified timeout
|
||||
*
|
||||
* Return code:
|
||||
* 0 Child finished cleanly (TERM)
|
||||
* 1 Child killed (KILL)
|
||||
* 2 Child not killed by KILL
|
||||
* -1 Syscall failed
|
||||
*
|
||||
**************************************/
|
||||
|
||||
int R;
|
||||
int child_status;
|
||||
|
||||
R = kill(child_pid, SIGTERM);
|
||||
if (R < 0)
|
||||
return ((errno == ESRCH) ? 0 : -1);
|
||||
|
||||
if (UTIL_set_handler(SIGALRM, alrm_handler, false) < 0)
|
||||
return -1;
|
||||
alarm(timeout_term);
|
||||
R = waitpid(child_pid, &child_status, 0);
|
||||
if ((R < 0) && !SYSCALL_INTERRUPTED(errno))
|
||||
return -1;
|
||||
if (R == child_pid)
|
||||
return 0;
|
||||
|
||||
R = kill(child_pid, SIGKILL);
|
||||
if (R < 0)
|
||||
return ((errno == ESRCH) ? 0 : -1);
|
||||
alarm(timeout_kill);
|
||||
R = waitpid(child_pid, &child_status, 0);
|
||||
if ((R < 0) && !SYSCALL_INTERRUPTED(errno))
|
||||
return -1;
|
||||
if (R == child_pid)
|
||||
return 1;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
int UTIL_ex_lock(const TEXT* file)
|
||||
{
|
||||
/**************************************
|
||||
@ -254,3 +318,37 @@ void UTIL_ex_unlock( int fd_file)
|
||||
close(fd_file);
|
||||
}
|
||||
|
||||
|
||||
int UTIL_set_handler(int sig, sighandler_t handler, bool restart)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* U T I L _ s e t _ h a n d l e r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
*
|
||||
* This function sets signal handler
|
||||
*
|
||||
**************************************/
|
||||
|
||||
#if defined(HAVE_SIGACTION)
|
||||
struct sigaction sig_action;
|
||||
if (sigaction(sig, NULL, &sig_action) < 0)
|
||||
return -1;
|
||||
sig_action.sa_handler = handler;
|
||||
if (restart)
|
||||
sig_action.sa_flags |= SA_RESTART;
|
||||
else
|
||||
sig_action.sa_flags &= ~SA_RESTART;
|
||||
if (sigaction(sig, &sig_action, NULL) < 0)
|
||||
return -1;
|
||||
#else
|
||||
sighandler_t old_handler = signal(SIGTERM, TERM_handler);
|
||||
if (old_handler == SIG_ERR)
|
||||
return -1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -24,10 +24,19 @@
|
||||
#ifndef UTIL_PROTO_H
|
||||
#define UTIL_PROTO_H
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
|
||||
pid_t UTIL_start_process(const char* process, char** argv);
|
||||
int UTIL_wait_for_child(pid_t child_pid);
|
||||
int UTIL_wait_for_child(pid_t child_pid,
|
||||
const volatile sig_atomic_t& shutting_down);
|
||||
int UTIL_shutdown_child(pid_t child_pid,
|
||||
unsigned timeout_term, unsigned timeout_kill);
|
||||
int UTIL_ex_lock(const char* file);
|
||||
void UTIL_ex_unlock(int fd_file);
|
||||
int UTIL_set_handler(int sig, sighandler_t handler, bool restart);
|
||||
|
||||
#endif // UTIL_PROTO_H
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user