/******************************************************************************* * Main.cc Tms process * T.Barnaby, BEAM Ltd, 2007-02-07 ******************************************************************************* */ #include <stdio.h> #include <syslog.h> #include <unistd.h> #include <signal.h> #include <sys/resource.h> #include <sys/mman.h> #include <main.h> #include <Control.h> #include <BDebug.h> #include <ucontext.h> #include <Debug.h> #define COREDUMP 0 typedef void (*SigFunction)(int, siginfo_t*, void*); Config config; Control* control; int realTime; void sigCrash(int sig, siginfo_t* sigInfo, void* context){ ucontext_t* ucontext = (ucontext_t*)context; char strBuf[1024]; time_t t; BDebugBacktrace bt; t = time(0); sprintf(strBuf, "TmsPuServer: Version %s crashed with signal %d at location: 0x%x accessing 0x%p on %s", VERSION, sig, ucontext->uc_mcontext.gregs[REG_EIP], sigInfo->si_addr, ctime(&t)); bt.dumpBacktraceSyslog(strBuf); bt.dumpBacktraceStdout(strBuf); _exit(1); } void sigAbort(int sig, siginfo_t* sigInfo, void* context){ control->abort(); _exit(1); } void signalSet(int sigNumber, SigFunction sigFunction){ struct sigaction sigAction; sigAction.sa_sigaction = sigFunction; sigemptyset(&sigAction.sa_mask); sigAction.sa_flags = SA_SIGINFO; sigAction.sa_restorer = 0; sigaction(sigNumber, &sigAction, 0); } void usage(){ fprintf(stderr, "Usage: tmsPuServer [-d n]\n"); fprintf(stderr, " -f : Run in the foreground\n"); fprintf(stderr, " -d n : Debug level n\n"); fprintf(stderr, " -n n : Set the number of this PuServer\n"); } int main(int argc, char** argv){ BError err; int a; BString s; int db = 0; int dbFixed = 0; int foreground = 0; int number = 0; sigset_t sigm; struct rlimit rlim; // Allow process to lock 500M of available memory rlim.rlim_max = 500*1024*1024; rlim.rlim_cur = rlim.rlim_max; if(setrlimit(RLIMIT_MEMLOCK, &rlim)) perror("Unable to enable memory locking"); #if COREDUMP rlim.rlim_max = 1024*1024*1024; rlim.rlim_cur = rlim.rlim_max; if(setrlimit(RLIMIT_CORE, &rlim)) perror("Unable to enable core dump"); printf("Set to core dump\n"); #endif // Relinqish root ownership if(geteuid() == 0){ realTime = 1; seteuid(getuid()); setegid(getgid()); } // Lock in all of the pages of this application if(mlockall(MCL_CURRENT | MCL_FUTURE) < 0) fprintf(stderr, "Warning: unable to lock in memory pages\n"); // Make sure master thread ignores termination signals sent to the other threads // Also ignore file size signal, the write function will return an error instead. sigemptyset(&sigm); sigaddset(&sigm, SIGUSR1); sigaddset(&sigm, SIGXFSZ); sigaddset(&sigm, SIGPIPE); sigaddset(&sigm, SIGALRM); sigprocmask(SIG_BLOCK, &sigm, 0); signalSet(SIGINT, sigAbort); signalSet(SIGTERM, sigAbort); #if !COREDUMP // Setup signals for program crash signalSet(SIGSEGV, sigCrash); signalSet(SIGHUP, sigCrash); signalSet(SIGILL, sigCrash); signalSet(SIGABRT, sigCrash); signalSet(SIGFPE, sigCrash); signalSet(SIGBUS, sigCrash); #endif openlog("TmsPuServer", LOG_CONS, LOG_DAEMON); nprintf("TmsPuServer version: %s started\n", VERSION); for(a = 1; a < argc; a++){ if(argv[a][0] == '-'){ switch(argv[a][1]){ case 'f': foreground = 1; break; case 'd': if(argc <= (a + 1)){ usage(); return 1; } setDebug(strtol(argv[++a], 0, 0)); dbFixed = 1; break; case 'n': if(argc <= (a + 1)){ usage(); return 1; } number = strtol(argv[++a], 0, 0); break; default: usage(); return 1; } } } // Open and read configuration if(config.open("tmsPuServerDebug.conf")) if(config.open("tmsPuServer.conf")) config.open("/etc/tmsPuServer.conf"); config.read(); if(!dbFixed){ s = config.findValue("Debug:"); if(s != ""){ db = strtol(s, 0, 0); setDebug(db); } } // Create daemon process if(!foreground) daemon(0, 0); // Create main control class control = new Control(dbFixed); if(err = control->init(number)){ eprintf("Error: %s\n", err.getString().retStr()); printf("Error: %s\n", err.getString().retStr()); return 1; } control->run(); return 0; }