mysqlmanager.cc File Reference

#include <my_global.h>
#include <my_sys.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "manager.h"
#include "options.h"
#include "log.h"

Include dependency graph for mysqlmanager.cc:

Include dependency graph

Enumerations

enum  { CHILD_OK = 0, CHILD_NEED_RESPAWN, CHILD_EXIT_ANGEL }

Functions

void init_environment (char *progname)
void daemonize (const char *log_file_name)
void angel (const Options &options)
int main (int argc, char *argv[])
void reap_child (int __attribute__((unused)) signo)
void terminate (int signo)

Variables

volatile sig_atomic_t child_status = CHILD_OK
volatile sig_atomic_t is_terminated = 0

Enumeration Type Documentation

anonymous enum
 

Enumeration values:
CHILD_OK 
CHILD_NEED_RESPAWN 
CHILD_EXIT_ANGEL 
00143 { CHILD_OK= 0, CHILD_NEED_RESPAWN, CHILD_EXIT_ANGEL };


Function Documentation

void angel const Options options  )  [static]
 

00192 {
00193   /* install signal handlers */
00194   sigset_t zeromask;                            // to sigsuspend in parent
00195   struct sigaction sa_chld, sa_term;
00196   struct sigaction sa_chld_out, sa_term_out, sa_int_out, sa_hup_out;
00197 
00198   sigemptyset(&zeromask);
00199   sigemptyset(&sa_chld.sa_mask);
00200   sigemptyset(&sa_term.sa_mask);
00201 
00202   sa_chld.sa_handler= reap_child;
00203   sa_chld.sa_flags= SA_NOCLDSTOP;
00204   sa_term.sa_handler= terminate;
00205   sa_term.sa_flags= 0;
00206 
00207   /* sigaction can fail only on wrong arguments */
00208   sigaction(SIGCHLD, &sa_chld, &sa_chld_out);
00209   sigaction(SIGTERM, &sa_term, &sa_term_out);
00210   sigaction(SIGINT, &sa_term, &sa_int_out);
00211   sigaction(SIGHUP, &sa_term, &sa_hup_out);
00212 
00213   /* spawn a child */
00214 spawn:
00215   pid_t pid= fork();
00216   switch (pid) {
00217   case -1:
00218     die("angel(): fork failed, %s", strerror(errno)); 
00219   case 0:                                     // child, success
00220     /*
00221       restore default actions for signals to let the manager work with
00222       signals as he wishes
00223     */ 
00224     sigaction(SIGCHLD, &sa_chld_out, 0);
00225     sigaction(SIGTERM, &sa_term_out, 0);
00226     sigaction(SIGINT, &sa_int_out, 0);
00227     sigaction(SIGHUP, &sa_hup_out, 0);
00228 
00229     manager(options.socket_file_name);
00230   default:                                    // parent, success
00231     while (child_status == CHILD_OK && is_terminated == 0)
00232       sigsuspend(&zeromask);
00233 
00234     if (is_terminated)
00235       log_info("angel got signal %d, exiting", is_terminated);
00236     else if (child_status == CHILD_NEED_RESPAWN)
00237     { 
00238       child_status= CHILD_OK;
00239       log_error("angel(): mysqlmanager exited abnormally: respawning...");
00240       sleep(1); /* don't respawn too fast */
00241       goto spawn;
00242     }
00243     /* mysqlmanager successfully exited, let's silently evaporate */
00244   }
00245 }

void daemonize const char *  log_file_name  )  [static]
 

00103 {
00104   pid_t pid= fork();
00105   switch (pid) {
00106   case -1:                                      // parent, fork error
00107     die("daemonize(): fork failed, %s", strerror(errno));
00108   case 0:                                       // child, fork ok
00109     int fd;
00110     /*
00111       Become a session leader: setsid must succeed because child is
00112       guaranteed not to be a process group leader (it belongs to the 
00113       process group of the parent.) 
00114       The goal is not to have a controlling terminal.
00115     */
00116     setsid();
00117     /*
00118       As we now don't have a controlling terminal we will not receive
00119       tty-related signals - no need to ignore them.
00120     */
00121 
00122     close(STDIN_FILENO);
00123 
00124     fd= open(log_file_name, O_WRONLY | O_CREAT | O_APPEND | O_NOCTTY, 
00125                  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
00126     if (fd < 0)
00127       die("daemonize(): failed to open log file %s, %s", log_file_name,
00128           strerror(errno));
00129     dup2(fd, STDOUT_FILENO);
00130     dup2(fd, STDERR_FILENO);
00131     if (fd != STDOUT_FILENO && fd != STDERR_FILENO)
00132       close(fd);
00133 
00134     /* TODO: chroot() and/or chdir() here */
00135     break;
00136   default:                                      
00137     /* successfully exit from parent */
00138     exit(0);
00139   }
00140 }

void init_environment char *  progname  )  [static]
 

00089 {
00090   MY_INIT(progname);
00091   log_init();
00092   umask(0117);
00093 }

int main int  argc,
char *  argv[]
 

00067 {
00068   init_environment(argv[0]);
00069   Options options;
00070   options.load(argc, argv);
00071   if (options.run_as_service)
00072   {
00073     daemonize(options.log_file_name);
00074     angel(options);
00075   }
00076   else
00077     manager(options.log_file_name);
00078   return 0;
00079 }

void reap_child int __attribute__((unused))  signo  ) 
 

00153 { 
00154   int child_exit_status;
00155   /* As we have only one child, no need to cycle waitpid */
00156   if (waitpid(0, &child_exit_status, WNOHANG) > 0)
00157   {
00158     if (WIFSIGNALED(child_exit_status))
00159       child_status= CHILD_NEED_RESPAWN;
00160     else
00161       /*
00162         As we reap_child is not called for SIGSTOP, we should be here only
00163         if the child exited normally.
00164       */
00165       child_status= CHILD_EXIT_ANGEL;
00166   }
00167 }

void terminate int  signo  ) 
 

00180 {
00181   is_terminated= signo; 
00182 }


Variable Documentation

volatile sig_atomic_t child_status = CHILD_OK [static]
 

volatile sig_atomic_t is_terminated = 0
 


Generated on Thu Feb 24 11:01:19 2005 for MySQL by  doxygen 1.3.9.1