/******************************************************************************* * 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; 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); #ifdef __x86_64__ sprintf(strBuf, "TmsServer: Version %s crashed with signal %d at location: 0x%x accessing 0x%p on %s", VERSION, sig, ucontext->uc_mcontext.gregs[REG_RIP], sigInfo->si_addr, ctime(&t)); #else sprintf(strBuf, "TmsServer: 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)); #endif bt.dumpBacktraceSyslog(strBuf); bt.dumpBacktraceStdout(strBuf); bt.dumpBacktraceFile("/var/log/tmsServerCrash", strBuf); bt.dumpBacktraceFile("/var/log/tmsServer.log", strBuf); _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: tmsServer [-c <filename> -f -d <n>]\n"); fprintf(stderr, " -c <filename> : Configuration file to use\n"); fprintf(stderr, " -f : Run in the foreground\n"); fprintf(stderr, " -d <n> : Debug level\n"); } int main(int argc, char** argv){ BError err; Control* control; int a; BString s; int db = 0; int dbFixed = 0; int foreground = 0; sigset_t sigm; struct rlimit rlim; BString configFile; // 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); sigprocmask(SIG_BLOCK, &sigm, 0); // Setup signals for program crash signalSet(SIGSEGV, sigCrash); signalSet(SIGHUP, sigCrash); signalSet(SIGILL, sigCrash); signalSet(SIGABRT, sigCrash); signalSet(SIGFPE, sigCrash); signalSet(SIGBUS, sigCrash); openlog("tmsServer", LOG_CONS, LOG_DAEMON); for(a = 1; a < argc; a++){ if(argv[a][0] == '-'){ switch(argv[a][1]){ case 'c': configFile = argv[++a]; break; case 'f': foreground = 1; break; case 'd': if(argc <= (a + 1)){ usage(); return 1; } setDebug(strtol(argv[++a], 0, 0)); dbFixed = 1; break; default: usage(); return 1; } } } // Open and read configuration if(configFile != ""){ if(err = config.open(configFile)){ eprintf("Error: Unable to open config file %s: %s\n", configFile.retStr(), err.getString().retStr()); printf("Error: Unable to open config file %s: %s\n", configFile.retStr(), err.getString().retStr()); return 1; } } else { if(config.open("tmsServerDebug.conf")) if(config.open("tmsServer.conf")) config.open("/etc/tmsServer.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()){ eprintf("Error: %s\n", err.getString().retStr()); printf("Error: %s\n", err.getString().retStr()); return 1; } control->run(); return 0; }