blob: 3e5c5e4e1badf233a8297b37631c4b6c811629d6 [file] [log] [blame]
#ifndef _PRAGMA_COPYRIGHT_
#define _PRAGMA_COPYRIGHT_
#pragma comment(copyright, "%Z% %I% %W% %D% %T%\0")
#endif /* _PRAGMA_COPYRIGHT_ */
/****************************************************************************
* Copyright (c) 2008, 2010 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0s
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
Classes: None
Description: SCI Service Daemon
Author: Tu HongJ, Nicole Nie, Liu Wei
History:
Date Who ID Description
-------- --- --- -----------
01/06/09 tuhongj Initial code (D155101)
09/04/12 ronglli Update the logging
****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <fstream>
#include "tools.hpp"
#include "log.hpp"
#include "locker.hpp"
#include "extlisten.hpp"
#include "extlaunch.hpp"
const int MAXFD = 128;
JOB_INFO jobInfo;
string pidFile;
struct sigaction oldSa;
void sig_term(int sig)
{
if (sig == SIGTERM) {
log_crit("Terminating ... ");
unlink(pidFile.c_str());
exit(0);
}
}
void daemonInit()
{
umask(0);
::sigaction(SIGCHLD, NULL, &oldSa);
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGUSR2, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
sa.sa_handler = sig_term;
sigaction(SIGTERM, &sa, NULL);
#if defined(_SCI_LINUX) || defined(__APPLE__)
pid_t pid;
if ((pid = fork()) < 0)
exit(-1);
else if (pid != 0) /* parent */
exit(0);
setsid();
#endif
chdir("/");
/* close off file descriptors */
for (int i = 0; i < MAXFD; i++)
close(i);
/* redirect stdin, stdout, and stderr to /dev/null */
open("/dev/null", O_RDONLY);
open("/dev/null", O_RDWR);
open("/dev/null", O_RDWR);
}
void writePidFile(string &pidf)
{
unlink(pidf.c_str());
ofstream pidfile(pidf.c_str());
if (!pidfile) {
printf("Cann't write pid file %s", pidf.c_str());
return;
}
pidfile << (int)getpid();
}
int checkPidFile(string &pidf)
{
ifstream pidfile(pidf.c_str());
if (!pidfile)
return 0;
string line;
pidfile >> line;
if (line.size() == 0)
return 0;
int pid = atoi(line.c_str());
if (kill(pid, 0) == 0)
return -1;
return 0;
}
void usage(char * pName)
{
printf("%s [-p pidDir] [-l logDir] [-s severity] [-e] \n\n", pName);
printf(" -p pidDir\t\tSpecify the pid directory. Default is: \"/var/run/\"(Linux) and \"/var/opt/\"(AIX)\n");
printf(" -l logDir\t\tSpecify the log directory. Default is: \"/tmp/\"\n");
printf(" -s severity\t\tSpecify the log severity. Default is: \"'3'(INFORMATION)\"\n");
printf(" -e \t\t\tEnable the log. Default is: disabled\n");
}
int initService(int argc, char *argv[])
{
int i;
char *optpattern = "hl:p:s:e";
char *prog = argv[0];
char *p = NULL;
string logDir = "/tmp";
int logLevel = Log::INFORMATION;
int logMode = Log::DISABLE;
#if defined(_SCI_LINUX) || defined(__APPLE__)
string pidDir = "/var/run/";
#else
string pidDir = "/var/opt/";
#endif
string logFile;
extern char *optarg;
extern int optind;
p = strrchr(prog, '/');
if (p != NULL)
p++;
else
p = prog;
while ((i = getopt(argc, argv, optpattern)) != EOF) {
switch (i) {
case 'l':
logDir = optarg;
break ;
case 'p':
pidDir = optarg;
break;
case 's':
logLevel = atoi(optarg);
break;
case 'e':
logMode = Log::ENABLE;
break;
case 'h':
usage(p);
exit(0);
break;
}
}
pidFile = pidDir + "/" + p + ".pid";
if (checkPidFile(pidFile) < 0) {
printf("%s is already running...\n", p);
return -1;
}
if (getuid() != 0) {
printf("Must running as root\n");
return -1;
}
daemonInit();
writePidFile(pidFile);
logFile = string(p) + ".log";
Log::getInstance()->init(logDir.c_str(), logFile.c_str(), logLevel, logMode);
return 0;
}
int main(int argc, char *argv[])
{
char *envp = NULL;
set_oom_adj(-1000);
if (initService(argc, argv) != 0)
return -1;
envp = ::getenv("SCI_DISABLE_IPV6");
if (envp && (::strcasecmp(envp, "yes") == 0)) {
Socket::setDisableIPv6(1);
}
ExtListener *listener = new ExtListener();
listener->start();
launcherList.clear();
while (1) {
Locker::getLocker()->freeze();
log_debug("Delete unused launcher");
Locker::getLocker()->lock();
vector<ExtLauncher *>::iterator lc;
for (lc = launcherList.begin(); lc != launcherList.end(); lc++) {
while (!(*lc)->isLaunched()) {
// before join, this thread should have been launched
SysUtil::sleep(WAIT_INTERVAL);
}
(*lc)->join();
delete (*lc);
}
launcherList.clear();
Locker::getLocker()->unlock();
log_info("Begin to cleanup the jobInfo");
Locker::getLocker()->lock();
JOB_INFO::iterator it;
for (it = jobInfo.begin(); it != jobInfo.end(); ) {
if ((SysUtil::microseconds() - it->second.timestamp) > FIVE_MINUTES) {
log_crit("Erase jobInfo item %d", it->first);
jobInfo.erase(it++);
} else {
++it;
}
}
log_info("Finish cleanup the jobInfo");
Locker::getLocker()->unlock();
}
listener->join();
delete listener;
delete Log::getInstance();
return 0;
}