8
0
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:
mkubecek 2006-08-16 12:46:15 +00:00
parent c9a0da0c0e
commit e9816e87af
3 changed files with 186 additions and 26 deletions

View File

@ -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 */

View File

@ -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;
}

View File

@ -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