bool checkDaemonExistence(const char* daemonName) { SingleLogger* logger = SingleLogger::InitLogger(); std::string serviceName(daemonName); bool isRunning = false; std::string pidFileName("/var/run/" + serviceName + ".pid"); std::ifstream pidFile(pidFileName.c_str(), std::ifstream::binary); if(pidFile.is_open()) { long pid = 0; std::string pidLine; if (pidFile.is_open()) { getline(pidFile, pidLine); pid = std::stoi(pidLine); kill(pid, 0); isRunning = !(errno == ESRCH); } } if (!isRunning) { std::ofstream pidFile(pidFileName.c_str(), std::ofstream::binary); if (pidFile.is_open()) { pidFile << getpid(); pidFile.close(); } else logger->logMessage(SingleLogger::WARNING, "pid file is not created"); } else logger->logMessage(SingleLogger::ERROR, "daemon already running"); return isRunning; }
bool PidFile::createPidFile( void ) { remove( fileName ); std::ofstream pidFile( fileName ); if( ! pidFile.good() ) { osErrno = errno; } else { pidFile << getpid() << std::endl; } if( ! pidFile.good() ) osErrno = errno; pidFile.close(); return( good() ); }
/*! * @brief Gets crash-reporter-daemon pid and saves it to file. * * @param app Reference to application. * @return True, if first startup; otherwise false. */ bool getPid(QCoreApplication &app) { QFile pidFile(CREPORTER_PID_FILE); qint64 pid = 0; bool firstStartup = true; // Get new PID. pid = app.applicationPid(); qDebug() << __PRETTY_FUNCTION__ << CReporter::DaemonBinaryName << "[" << pid << "] starting..."; if (pidFile.exists()) { firstStartup = false; qDebug() << __PRETTY_FUNCTION__ << "Removing stale PID file."; pidFile.remove(); } if (pidFile.open(QIODevice::WriteOnly)) { QTextStream out(&pidFile); out << pid; pidFile.close(); } qDebug() << __PRETTY_FUNCTION__ << "Startup delayed =" << firstStartup; return firstStartup; }
int Dynamic::getPid() const { QFile pidFile(Utils::cacheDir(constDir, false)+constLockFile); if (pidFile.open(QIODevice::ReadOnly|QIODevice::Text)) { QTextStream str(&pidFile); int pid=0; str >> pid; return pid; }
/** * Stop a previously started Xrootd server * * @return true if stopped, false otherwise */ static Bool_t StopXrootd() { std::ifstream pidFile("xrd.pid"); if (!pidFile) return false; TString s; s.ReadFile(pidFile); pidFile.close(); gSystem->Unlink("xrd.pid"); if (s.IsNull()) return false; Info("StopXrootd", "Stopping XRootd server (pid: %s)", s.Data()); return gSystem->Exec(Form("kill -9 %s", s.Data())) == 0; }
/** * Write a file containing the process id to current directory. * File name is written as "prefix.suffix.pid" * @parma prefix arbitrary string prefix (can be NULL) for filename * @param suffix arbitrary string suffix (can be NULL) * @param pid the current process id * @parma ppid the curren process parent id - NOT USED junk for now * @return 0 on success */ int WritePidFile(const char* prefix, const char* suffix, pid_t pid, pid_t ppid) { std::string pidFileName = std::string(prefix) + "." + suffix + std::string(".pid"); std::ofstream pidFile(pidFileName); if (pidFile.is_open()) { pidFile << pid; pidFile.flush(); pidFile.close(); return (0); } else { return (-1); } }
bool isRun(qint64 pid) { QString pidPath(QDir::homePath()); pidPath=pidPath+"/.config/qxkb.pid"; qDebug()<<"Pid file locate :"<<pidPath; QFile pidFile(pidPath); QDir proc(QString("/proc")); if (pidFile.exists()) { qDebug()<<"File exist check pid"; if (!pidFile.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug()<<"Faled open file"; return false; } QStringList proccessList=proc.entryList(QDir::Dirs); qDebug()<<"Proc list "<<proccessList; QTextStream in(&pidFile); while (!in.atEnd()) { QString pidString = in.readLine(); qDebug()<<"Get exist pid"<<pidString; int index = proccessList.indexOf(pidString.trimmed()); qDebug()<<"Index pid in list"<<index; if (index<0) { pidFile.close(); pidFile.remove(); } else { QString pidExist=proccessList.at(index); qDebug()<<"Compare processname: "<<pidExist; if (getName(pidExist)=="qxkb") { pidFile.close(); return true; } } } pidFile.close(); pidFile.remove(); } if (!pidFile.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug()<<"Faled to create pid"; return false; } qDebug()<<"Create pid"; QTextStream out(&pidFile); out << QString::number(pid); pidFile.close(); return false; }
long Dialog::verifyPidFile() { QMessageBox messageBox; char *charPid = new char[pidLength]; char *endPtr; long pidNumber; int charPidLen; QString configPathQStr(configPathStr.c_str()); QString pidFileQStr(pidFileStr.c_str()); QFile pidFile(configPathQStr + pidFileQStr); if (!pidFile.exists()) { messageBox.information(this, "File not found", "Could not find the PID file"); return -1; } if (!pidFile.open(QFile::ReadOnly)) { messageBox.information(this, "Could not open", "Could not open the pid file"); return -1; } if (0 >= pidFile.readLine(charPid, sizeof(charPid))) { messageBox.information(this, "Invalid read", "Could not read"); return -1; } /* readLine sempre coloca \n no final, se nao encontrar */ charPidLen = strlen(charPid); pidNumber = strtol(charPid, &endPtr, numberBase); if (charPidLen != endPtr - charPid) { messageBox.information(this, "Invalid PID", "Invalid PID number"); return -1; } pidFile.close(); return pidNumber; }
void writePidToFile() { UtlString pidFileName = SipXecsService::Path(SipXecsService::RunDirType, SUPERVISOR_PID_FILE); char pidString[1024]; sprintf(pidString, "%ld\n", (long)getpid()); OsFile pidFile(pidFileName); if ( OS_SUCCESS == pidFile.open(OsFile::CREATE) ) { size_t bytesWritten; if ( OS_SUCCESS != pidFile.write(pidString, strlen(pidString), bytesWritten) ) { osPrintf("sipXsupervisor: could not write pidFile %s\n", pidFileName.data()); } pidFile.close(); } else { osPrintf("sipXsupervisor: could not open pidFile %s\n", pidFileName.data()); } }
int daemonShutdown(const String& daemonName, const ServiceEnvironmentIFCRef& env) { #ifndef WIN32 #if defined(OW_NETWARE) (void)daemonName; { NonRecursiveMutexLock l(g_shutdownGuard); g_shutDown = true; g_shutdownCond.notifyAll(); pthread_yield(); } if(!FromEventHandler) { UnRegisterEventNotification(DownEvent); } #else String pidFile(env->getConfigItem(ConfigOpts::PIDFILE_opt, OW_DEFAULT_PIDFILE)); PidFile::removePid(pidFile.c_str()); #endif #endif shutdownSig(); return 0; }
int startDaemon() { pid_t pid; pid = fork(); ///NOTE: version in trunk checks for CHILD, not 0... if( pid < 0 ) exit( EXIT_FAILURE ); if( pid > 0 ) exit( EXIT_SUCCESS ); ///NOTE: version in trunk checks for ERROR not 0... if( setsid() < 0 ) exit( EXIT_FAILURE ); /// change to root in file system if( ( chdir( "/" ) ) < 0 ) exit( EXIT_FAILURE ); umask( 0 ); for( int i = sysconf( _SC_OPEN_MAX ); i > 0; i-- ) close( i ); /// check if the directory for pid file exist ifstream fin; string path = "/tmp/wonder"; fin.open( path.c_str() , ios_base::in ); if( !fin.is_open() ) { /// create /tmp/wonder directory if it does not exist yet /// the sticky: anyone is able to create files, but /// not able to delete anyone elses files but their own int error = mkdir( path.c_str(), mode_t(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX)); if( error != 0 ) return 1; } /// open file stream to write the pid in string name; ostringstream spid; /// get pid of parent process spid << getpid(); if( twonderConf->user == NULL ) pathPidfile = path + "/twonder." + spid.str() + ".pid"; else pathPidfile = path + "/twonder." + ( string ) twonderConf->user + ".pid"; ofstream pidFile( pathPidfile.c_str() ); pidFile << spid.str(); pidFile.close(); /// write stdin to /dev/null freopen("/dev/null", "r", stdin ); /// write stdout and stderr to the log file freopen( "/var/log/wonder.log", "w", stdout ); freopen( "/var/log/wonder.log", "w", stderr ); return 0; }
/** * Main entry point for the application. */ int main (int argc, char* argv[]) { // Initialise the debug flags crt_init(); // Set the stream references for rMessage(), redirect std::cout, etc. applog::initialiseLogStreams(); // Initialise the context (application path / settings path, is OS-specific) module::ModuleRegistry::Instance().initialiseContext(argc, argv); // Acquire the appplication context ref (shortcut) const ApplicationContext& ctx = module::getRegistry().getApplicationContext(); // The settings path is set, start logging now applog::LogFile::create("darkradiant.log"); #ifndef POSIX // Initialise the language based on the settings in the user settings folder // This needs to happen before gtk_init() to set up the environment for GTK language::LanguageManager().init(ctx); #endif // Initialise gtkmm (don't set locale on Windows) #ifndef POSIX Gtk::Main gtkmm_main(argc, argv, false); #else Gtk::Main gtkmm_main(argc, argv, true); #ifndef LOCALEDIR #error LOCALEDIR not defined #endif // Other POSIX gettext initialisation setlocale(LC_ALL, ""); textdomain(GETTEXT_PACKAGE); bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); #endif // Initialise Glib threading if necessary if (!Glib::thread_supported()) { Glib::thread_init(); } Glib::add_exception_handler(&std::terminate); #ifdef HAVE_GTKSOURCEVIEW // Initialise gtksourceviewmm gtksourceview::init(); #endif // Initialise GTKGLExtmm Gtk::GL::init(argc, argv); // reset some locale settings back to standard c // this is e.g. needed for parsing float values from textfiles setlocale(LC_NUMERIC, "C"); setlocale(LC_TIME, "C"); // Now that GTK is ready, activate the Popup Error Handler module::ModuleRegistry::Instance().initErrorHandler(); { // Create the radiant.pid file in the settings folder // (emits a warning if the file already exists (due to a previous startup failure)) applog::PIDFile pidFile(PID_FILENAME); ui::Splash::Instance().show_all(); // Initialise the Reference in the GlobalModuleRegistry() accessor. module::RegistryReference::Instance().setRegistry(module::getRegistry()); ui::Splash::Instance().setProgressAndText(_("Searching for Modules"), 0.0f); // Invoke the ModuleLoad routine to load the DLLs from modules/ and plugins/ #if defined(POSIX) && defined(PKGLIBDIR) // Load modules from compiled-in path (e.g. /usr/lib/darkradiant) module::Loader::loadModules(PKGLIBDIR); #else // Load modules from application-relative path module::Loader::loadModules(ctx.getApplicationPath()); #endif module::getRegistry().initialiseModules(); radiant::getGlobalRadiant()->postModuleInitialisation(); // Delete the splash screen here ui::Splash::Instance().destroy(); // Scope ends here, PIDFile is deleted by its destructor } // greebo: Check if we should run an automated test if (!profile::CheckAutomatedTestRun()) { // Start the GTK main loop. This will run until a quit command is given by // the user Gtk::Main::run(); } GlobalMap().freeMap(); GlobalMainFrame().destroy(); // Issue a shutdown() call to all the modules module::GlobalModuleRegistry().shutdownModules(); // Close the logfile applog::LogFile::close(); applog::shutdownStreams(); return EXIT_SUCCESS; }
int CIMListenerProcess::cimserver_run( int argc, char** argv, Boolean shutdownOption, Boolean debugOutputOption) { String logsDirectory; String homeDir = configManager->getListenerHome(); // // Get an instance of the Config Manager. // //configManager = DynamicListenerConfig::getInstance(); // // Check to see if we should Pegasus as a daemon // Boolean daemonOption; #if defined(PEGASUS_OS_TYPE_WINDOWS) daemonOption = false; #else daemonOption = true; for (int i=1; i < argc; i++) { if (strcmp(argv[i], OPTION_NO_DAEMON) == 0) { daemonOption = false; break; } } #endif // // Get options (from command line and from configuration file); this // removes corresponding options and their arguments from the command // line. // try { String configFilePath = homeDir + "/" + DEFAULT_CONFIG_FILE; FileSystem::translateSlashes(configFilePath); configManager->initOptions(configFilePath); } catch (Exception& e) { MessageLoaderParms parms("DynListener.cimlistener.LISTENER_NOT_STARTED", "CIM Listener not started: $0", e.getMessage()); Logger::put_l(Logger::ERROR_LOG, System::CIMLISTENER, Logger::SEVERE, parms); PEGASUS_STD(cerr) << argv[0] << ": " << MessageLoader::getMessage(parms) << PEGASUS_STD(endl); return(1); } // l10n // Set the home directory, msg sub-dir, into the MessageLoader. // This will be the default directory where the resource bundles // are found. String msgHome = homeDir + "/msg"; FileSystem::translateSlashes(msgHome); MessageLoader::setPegasusMsgHome(msgHome); // // Check to see if we need to shutdown CIMOM // if (shutdownOption) { //gracefully exit //Uncomment the following line when signals are implemented on all //platforms. //The workaround is to use a file. #ifdef PEGASUS_HAS_SIGNALS PidFile pidFile(LISTENER_START_FILE); PEGASUS_PID_T pid = (PEGASUS_PID_T) pidFile.getPid(); if (pid == 0) { pidFile.remove(); return (-1); } int rc = kill(pid, PEGASUS_SIGTERM); // check for success or failure of the kill operation if (rc == -1) { if (errno == EPERM) { MessageLoaderParms parms( "DynListener.cimlistener.KILL_PERM_DENIED", "Permission denied: Not permitted to" "shutdown cimlistener process."); cout << MessageLoader::getMessage(parms) << endl; } else { MessageLoaderParms parms( "DynListener.cimlistener.KILL_FAILED", "Failed to shutdown cimlistener process. Error: \"$1\"", strerror(errno)); cout << MessageLoader::getMessage(parms) << endl; } return(rc); } //cimserver_kill(1); #else #if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_OS_LINUX) \ || defined(PEGASUS_OS_ZOS) \ || defined(PEGASUS_OS_AIX) || defined(PEGASUS_OS_PASE) \ || defined(PEGASUS_OS_SOLARIS) \ || defined(PEGASUS_OS_VMS) // Check to see if the CIM Listener is running. // No need to stop if not running. if (_serverRunStatus.isServerRunning()) { PidFile pidFile(LISTENER_STOP_FILE); pidFile.setPid(System::getPID()); } else { printf("CIM Listener may not be running.\n"); return(0); } #endif #endif //PEGASUS_HAS_SIGNALS //l10n //cout << "CIM Server stopped." << endl; MessageLoaderParms parms("DynListener.cimlistener.LISTENER_STOPPED", "CIM Listener stopped."); cout << MessageLoader::getMessage(parms) << endl; return(0); } //get config options. //note that the paths will be converted to homedPaths in the lookup calls. Uint32 listenerPort; Boolean httpsConnection; String sslKeyFilePath; String sslCertificateFilePath; String sslCipherSuite; String consumerDir; String consumerConfigDir; Boolean enableConsumerUnload; Uint32 consumerIdleTimeout; Uint32 shutdownTimeout; String traceFile; Uint32 traceLevel; String traceComponents; try { configManager->lookupIntegerValue("listenerPort", listenerPort); httpsConnection = configManager->isTrue("enableHttpsListenerConnection"); configManager->lookupValue("sslKeyFilePath", sslKeyFilePath); configManager->lookupValue("sslCertificateFilePath", sslCertificateFilePath); if(!configManager->lookupValue("sslCipherSuite",sslCipherSuite)) { throw InvalidPropertyValue("sslCipherSuite",sslCipherSuite); } configManager->lookupValue("consumerDir", consumerDir); configManager->lookupValue("consumerConfigDir", consumerConfigDir); enableConsumerUnload = configManager->isTrue("enableConsumerUnload"); configManager->lookupIntegerValue("consumerIdleTimeout", consumerIdleTimeout); configManager->lookupIntegerValue("consumerIdleTimeout", consumerIdleTimeout); configManager->lookupIntegerValue("shutdownTimeout", shutdownTimeout); configManager->lookupValue("traceFilePath", traceFile); configManager->lookupIntegerValue("traceLevel", traceLevel); configManager->lookupValue("traceComponents", traceComponents); } catch (Exception& ex) { cout << ex.getMessage() << endl; exit(0); } //Check listener port validity //ATTN: Do we need this? /*CString portString = listenerPort.getCString(); char* end = 0; Uint32 port = strtol(portString, &end, 10); if(!(end != 0 && *end == '\0')) { PEGASUS_STD(cerr) << "Bad HTTP/HTTPS Port Value" << PEGASUS_STD(endl); exit(1); }*/ //Configure trace options if (traceLevel > 0) { Uint32 traceLevelArg = 0; switch (traceLevel) { case 1: traceLevelArg = Tracer::LEVEL1; break; case 2: traceLevelArg = Tracer::LEVEL2; break; case 3: traceLevelArg = Tracer::LEVEL3; break; case 4: traceLevelArg = Tracer::LEVEL4; break; default: break; } Tracer::setTraceFile((const char*)traceFile.getCString()); Tracer::setTraceComponents(traceComponents); Tracer::setTraceLevel(traceLevelArg); } #if defined(PEGASUS_DEBUG) { // Put out startup up message. cout << _cimListenerProcess->getProductName() << " " << _cimListenerProcess->getVersion() << endl; MessageLoaderParms parms("DynListener.cimlistener.STARTUP_MESSAGE", "CIM Listener built $0 $1\nCIM Listener starting...", __DATE__, __TIME__); } #endif //l10n // reset message loading to NON-process locale MessageLoader::_useProcessLocale = false; //l10n // Get the parent's PID before forking _serverRunStatus.setParentPid(System::getPID()); // do we need to run as a daemon ? if (daemonOption) { if(-1 == _cimListenerProcess->cimserver_fork()) { return(-1); } } // l10n // Now we are after the fork... // Create a dummy Thread object that can be used to store the // AcceptLanguageList object for CIM requests that are serviced // by this thread (initial thread of server). Need to do this // because this thread is not in a ThreadPool, but is used // to service CIM requests. // The run function for the dummy Thread should never be called, Thread *dummyInitialThread = new Thread(dummyThreadFunc, NULL, false); Thread::setCurrent(dummyInitialThread); try { Thread::setLanguages(LanguageParser::getDefaultAcceptLanguages()); } catch(InvalidAcceptLanguageHeader& e) { Logger::put_l(Logger::ERROR_LOG, System::CIMLISTENER, Logger::SEVERE, MessageLoaderParms( "src.Server.cimserver.FAILED_TO_SET_PROCESS_LOCALE", "Could not convert the system process" "locale into a valid AcceptLanguage format.")); Logger::put(Logger::ERROR_LOG, System::CIMLISTENER, Logger::SEVERE, e.getMessage()); } #if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) \ || defined(PEGASUS_OS_ZOS) || defined(PEGASUS_OS_AIX) \ || defined(PEGASUS_OS_PASE) \ || defined(PEGASUS_OS_SOLARIS) || defined (PEGASUS_OS_VMS) umask(S_IWGRP|S_IWOTH); // // check if CIMServer is already running // if CIMServer is already running, print message and // notify parent process (if there is a parent process) to terminate // if (_serverRunStatus.isServerRunning()) { MessageLoaderParms parms( "DynListener.cimlistener.UNABLE_TO_START_LISTENER_ALREADY_RUNNING", "Unable to start CIM Listener.\nCIM Listener is already running."); PEGASUS_STD(cerr) << MessageLoader::getMessage(parms) << PEGASUS_STD(endl); // // notify parent process (if there is a parent process) to terminate // if (daemonOption) { _cimListenerProcess->notify_parent(1); } return 1; } #endif // try loop to bind the address, and run the server try { #ifdef PEGASUS_HAS_SSL //create DynListener if (httpsConnection) { _cimListener = new DynamicListener( listenerPort, consumerDir, consumerConfigDir, true, sslKeyFilePath, sslCertificateFilePath, enableConsumerUnload, consumerIdleTimeout, shutdownTimeout, sslCipherSuite); } else #endif { _cimListener = new DynamicListener( listenerPort, consumerDir, consumerConfigDir, enableConsumerUnload, consumerIdleTimeout, shutdownTimeout); } _cimListener->start(); Logger::put_l(Logger::STANDARD_LOG, System::CIMLISTENER, Logger::INFORMATION, MessageLoaderParms( "DynListener.cimlistener.LISTENING_ON_PORT", "The CIM listener is listening on port $0.", listenerPort)); #if defined(PEGASUS_DEBUG) //Log startup options printf("Starting CIMListener with the following options\n"); printf("\tlistenerPort %u\n", listenerPort); printf("\thttpsConnection %d\n", httpsConnection); printf("\tsslKeyFilePath %s\n", (const char*)sslKeyFilePath.getCString()); printf("\tsslCertificateFilePath %s\n", (const char*)sslCertificateFilePath.getCString()); printf("\tsslCipherSuite %s\n", (const char*)sslCipherSuite.getCString()); printf("\tconsumerDir %s\n", (const char*)consumerDir.getCString()); printf("\tconsumerConfigDir %s\n", (const char*)consumerConfigDir.getCString()); printf("\tenableConsumerUnload %d\n", enableConsumerUnload); printf("\tconsumerIdleTimeout %u\n", consumerIdleTimeout); printf("\tshutdownTimeout %u\n", shutdownTimeout); printf("\ttraceFilePath %s\n", (const char*)traceFile.getCString()); printf("\ttraceLevel %u\n", traceLevel); printf("\ttraceComponents %s\n", (const char*)traceComponents.getCString()); printf("\tMessage home is %s\n", (const char*)msgHome.getCString()); #endif // notify parent process (if there is a parent process) to terminate // so user knows that there is cimserver ready to serve CIM requests. if (daemonOption) _cimListenerProcess->notify_parent(0); #if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_OS_LINUX) || \ defined(PEGASUS_OS_ZOS) || defined(PEGASUS_OS_AIX) || \ defined(PEGASUS_OS_PASE) || \ defined(PEGASUS_OS_SOLARIS) || defined(PEGASUS_OS_VMS) // // create a file to indicate that the cimserver has started and // save the process id of the cimserver process in the file // _serverRunStatus.setServerRunning(); #endif //#if defined(PEGASUS_DEBUG) cout << "Started. " << endl; //#endif // Put server started message to the logger Logger::put_l(Logger::STANDARD_LOG, System::CIMLISTENER, Logger::INFORMATION, MessageLoaderParms( "src.Server.cimserver.STARTED_VERSION", "Started $0 version $1.", _cimListenerProcess->getProductName(), _cimListenerProcess->getVersion())); #if defined(PEGASUS_OS_TYPE_UNIX) if (daemonOption && !debugOutputOption) { // Direct standard input, output, and error to /dev/null, // since we are running as a daemon. close(0); open("/dev/null", O_RDONLY); close(1); open("/dev/null", O_RDWR); close(2); open("/dev/null", O_RDWR); } #endif #if !defined(PEGASUS_OS_TYPE_WINDOWS) // if signals are defined, do not use old file creation mechanism #ifndef PEGASUS_HAS_SIGNALS #if defined(PEGASUS_DEBUG) printf("Blocking until shutdown signal\n"); #endif while (true) { if (FileSystem::exists(LISTENER_STOP_FILE)) { break; } Threads::sleep(500); } #if defined(PEGASUS_DEBUG) printf("Received signal to shutdown\n"); #endif FileSystem::removeFile(LISTENER_STOP_FILE); _cimListener->stop(); #else // defined(PEGASUS_HAS_SIGNALS) //Temporary workaround is to use a file, as specified above. //wait until signalled to terminate int sig = _cimListenerProcess->cimserver_wait(); #if defined(PEGASUS_DEBUG) printf("Returned from sigwait %d\n", sig); #endif if ((sig == PEGASUS_SIGTERM) || (sig == PEGASUS_SIGHUP)) { #if defined(PEGASUS_DEBUG) printf("Graceful shutdown\n"); #endif _cimListener->stop(); } #endif #else //ATTN: Implement cimserver_wait for windows //so we don't have to loop here //The listener is stopped in the cimserver_stop method //by the service control manager while (true) { if (!_cimListener->isAlive()) { break; } Sleep(500); } #endif #if defined(PEGASUS_DEBUG) PEGASUS_STD(cout) << "Stopped\n"; #endif // // normal termination // // Put server shutdown message to the logger Logger::put_l(Logger::STANDARD_LOG, System::CIMLISTENER, Logger::INFORMATION, MessageLoaderParms( "src.Server.cimserver.STOPPED", "$0 stopped.", _cimListenerProcess->getProductName())); } catch (Exception& e) { Logger::put_l( Logger::STANDARD_LOG, System::CIMLISTENER, Logger::WARNING, MessageLoaderParms( "src.Server.cimserver.ERROR", "Error: $0", e.getMessage())); MessageLoaderParms parms("DynListener.cimlistener.ERROR", "CIM Listener error: $0"); PEGASUS_STD(cerr) << MessageLoader::getMessage(parms) << PEGASUS_STD(endl); // // notify parent process (if there is a parent process) to terminate // if (daemonOption) _cimListenerProcess->notify_parent(1); delete _cimListener; _cimListener = 0; return 1; } delete _cimListener; _cimListener = 0; #if defined(PEGASUS_DEBUG) printf("Exiting child process\n"); #endif return 0; }
/** * daemonize() - detach process from user and disappear into the background * Throws DaemonException on error. */ void daemonize(bool dbgFlg, const String& daemonName, const ServiceEnvironmentIFCRef& env) { #ifndef WIN32 #ifdef OW_NETWARE { NonRecursiveMutexLock l(g_shutdownGuard); g_shutDown = false; } #endif initDaemonizePipe(); // If we're running as root and owcimomd.drop_root_privileges != "false", then try to switch users/groups to owcimomd/owcimomd if (geteuid() == 0 && !env->getConfigItem(ConfigOpts::DROP_ROOT_PRIVILEGES_opt, OW_DEFAULT_DROP_ROOT_PRIVILEGES).equalsIgnoreCase("false")) { const char OWCIMOMD_USER[] = "owcimomd"; // dont need to worry about thread safety here, the threads won't start until later. struct passwd* owcimomdInfo = ::getpwnam(OWCIMOMD_USER); if (!owcimomdInfo) { OW_THROW_ERRNO_MSG(DaemonException, "Platform::daemonize(): getpwnam(\"owcimomd\")"); } if (::setgid(owcimomdInfo->pw_gid) != 0) { OW_THROW_ERRNO_MSG(DaemonException, "Platform::daemonize(): setgid"); } if (::initgroups(owcimomdInfo->pw_name, owcimomdInfo->pw_gid) != 0) { OW_THROW_ERRNO_MSG(DaemonException, "Platform::daemonize(): initgroups"); } if (::setuid(owcimomdInfo->pw_uid) != 0) { OW_THROW_ERRNO_MSG(DaemonException, "Platform::daemonize(): setuid"); } } int pid = -1; #if !defined(OW_NETWARE) String pidFile(env->getConfigItem(ConfigOpts::PIDFILE_opt, OW_DEFAULT_PIDFILE)); pid = PidFile::checkPid(pidFile.c_str()); // Is there already another instance of the cimom running? if (pid != -1) { OW_THROW(DaemonException, Format("Another instance of %1 is already running [%2]", daemonName, pid).c_str()); } #endif if (!dbgFlg) { #if !defined(OW_NETWARE) && !defined(WIN32) pid = fork(); switch (pid) { case 0: break; case -1: OW_THROW_ERRNO_MSG(DaemonException, "FAILED TO DETACH FROM THE TERMINAL - First fork"); default: int status = DAEMONIZE_FAIL; if (daemonize_upipe->readInt(&status) < 1 || status != DAEMONIZE_SUCCESS) { cerr << "Error starting CIMOM. Check the log files." << endl; _exit(1); } _exit(0); // exit the original process } if (setsid() < 0) // shoudn't fail on linux { OW_THROW(DaemonException, "FAILED TO DETACH FROM THE TERMINAL - setsid failed"); } pid = fork(); switch (pid) { case 0: break; case -1: { // Save the error number, since the sendDaemonizeStatus function can cause it to change. int saved_errno = errno; sendDaemonizeStatus(DAEMONIZE_FAIL); // Restore the real error number. errno = saved_errno; OW_THROW_ERRNO_MSG(DaemonException, "FAILED TO DETACH FROM THE TERMINAL - Second fork"); exit(1); } default: _exit(0); } #endif chdir("/"); close(0); close(1); close(2); open("/dev/null", O_RDONLY); open("/dev/null", O_WRONLY); dup(1); } else { pid = getpid(); } umask(0077); // ensure all files we create are only accessible by us. #if !defined(OW_NETWARE) if (PidFile::writePid(pidFile.c_str()) == -1) { // Save the error number, since the sendDaemonizeStatus function can cause it to change. int saved_errno = errno; sendDaemonizeStatus(DAEMONIZE_FAIL); // Restore the real error number. errno = saved_errno; OW_THROW_ERRNO_MSG(DaemonException, Format("Failed to write the pid file (%1)", pidFile).c_str()); } #endif OW_LOG_INFO(env->getLogger(COMPONENT_NAME), Format("Platform::daemonize() pid = %1", ::getpid())); #endif initSig(); #ifndef WIN32 setupSigHandler(dbgFlg); #endif #ifdef OW_HAVE_PTHREAD_ATFORK // this registers shutdownSig to be run in the child whenever a fork() happens. // This will prevent a child process from writing to the signal pipe and shutting down the parent. ::pthread_atfork(NULL, NULL, &shutdownSig); #endif }
int _SMERP_posixMain( int argc, char* argv[] ) { // i18n global stuff if ( setlocale( LC_ALL, "" ) == NULL ) { std::cerr << "Unable to set locale. Falling back to default." << std::endl; } else { if ( bindtextdomain( "SMERP", "../po" ) == NULL ) { std::cerr << "Not enough memory to bind textdomain" << std::endl; return _SMERP::ErrorCodes::FAILURE; } if ( textdomain( "SMERP" ) == NULL ) { std::cerr << "Not enough memory to set textdomain" << std::endl; return _SMERP::ErrorCodes::FAILURE; } } // end of i18n global stuff try { _SMERP::Version appVersion( MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER ); _SMERP::CmdLineConfig cmdLineCfg; const char *configFile; // it's just a DUMMY for now _SMERP::HandlerConfiguration handlerConfig; if ( !cmdLineCfg.parse( argc, argv )) { // there was an error parsing the command line std::cerr << cmdLineCfg.errMsg() << std::endl << std::endl; cmdLineCfg.usage( std::cerr ); std::cerr << std::endl; return _SMERP::ErrorCodes::FAILURE; } // command line has been parsed successfully // if cmdLineCfg.errMsg() is not empty than we have a warning if ( !cmdLineCfg.errMsg().empty() ) // there was a warning parsing the command line std::cerr << "BOO:" << cmdLineCfg.errMsg() << std::endl << std::endl; // if we have to print the version or the help do it and exit if ( cmdLineCfg.command == _SMERP::CmdLineConfig::PRINT_VERSION ) { std::cout << std::endl << gettext( "BOBOBO version " ) << appVersion.toString() << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } if ( cmdLineCfg.command == _SMERP::CmdLineConfig::PRINT_HELP ) { std::cout << std::endl << gettext( "BOBOBO version " ) << appVersion.toString() << std::endl; cmdLineCfg.usage( std::cout ); std::cout << std::endl; return _SMERP::ErrorCodes::OK; } // decide what configuration file to use if ( !cmdLineCfg.cfgFile.empty() ) // if it has been specified than that's The One ! (and only) configFile = cmdLineCfg.cfgFile.c_str(); else configFile = _SMERP::CfgFileConfig::chooseFile( DEFAULT_MAIN_CONFIG, DEFAULT_USER_CONFIG, DEFAULT_LOCAL_CONFIG ); if ( configFile == NULL ) { // there is no configuration file std::cerr << gettext ( "MOMOMO: no configuration file found !" ) << std::endl << std::endl; return _SMERP::ErrorCodes::FAILURE; } _SMERP::CfgFileConfig cfgFileCfg; if ( !cfgFileCfg.parse( configFile )) { // there was an error parsing the configuration file std::cerr << cfgFileCfg.errMsg() << std::endl << std::endl; return _SMERP::ErrorCodes::FAILURE; } else if ( !cfgFileCfg.errMsg().empty()) std::cerr << cfgFileCfg.errMsg() << std::endl; // configuration file has been parsed successfully // build the application configuration _SMERP::ApplicationConfiguration config( cmdLineCfg, cfgFileCfg); // now here we know where to log to on stderr _SMERP::LogBackend::instance().setConsoleLevel( config.stderrLogLevel ); // Check the configuration if ( cmdLineCfg.command == _SMERP::CmdLineConfig::CHECK_CONFIG ) { std::cout << std::endl << gettext( "BOBOBO version " ) << appVersion.toString() << std::endl; if ( config.check() ) { if ( config.errMsg().empty() ) { std::cout << "Configuration OK" << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } else { std::cout << "WARNING: " << config.errMsg() << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } } else { std::cout << "ERROR: " << config.errMsg() << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } } if ( cmdLineCfg.command == _SMERP::CmdLineConfig::PRINT_CONFIG ) { std::cout << std::endl << gettext( "BOBOBO version " ) << appVersion.toString() << std::endl; config.print( std::cout ); std::cout << std::endl; return _SMERP::ErrorCodes::OK; } if ( cmdLineCfg.command == _SMERP::CmdLineConfig::TEST_CONFIG ) { std::cout << "Not implemented yet" << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } // Daemon stuff if( !config.foreground ) { // Aba: maybe also in the foreground? // try to lock the pidfile, bail out if not possible if( boost::filesystem::exists( config.pidFile ) ) { boost::interprocess::file_lock lock( config.pidFile.c_str( ) ); if( lock.try_lock( ) ) { std::cerr << "Pidfile is locked, another daemon running?" << std::endl; return _SMERP::ErrorCodes::FAILURE; } } // daemonize, lose process group, terminal output, etc. if( daemon( 0, 0 ) ) { std::cerr << "Daemonizing server failed" << std::endl; return _SMERP::ErrorCodes::FAILURE; } // now here we lost constrol over the console, we should // create a temporary logger which at least tells what's // going on in the syslog _SMERP::LogBackend::instance().setSyslogLevel( config.syslogLogLevel ); _SMERP::LogBackend::instance().setSyslogFacility( config.syslogFacility ); _SMERP::LogBackend::instance().setSyslogIdent( config.syslogIdent ); // if we are root we can drop privileges now struct group *groupent; struct passwd *passwdent; groupent = getgrnam( config.group.c_str( ) ); passwdent = getpwnam( config.user.c_str( ) ); if( groupent == NULL || passwdent == NULL ) { LOG_CRITICAL << "Illegal group '" << config.group << "' or user '" << config.user << "'"; return _SMERP::ErrorCodes::FAILURE; } if( setgid( groupent->gr_gid ) < 0 ) { LOG_CRITICAL << "setgid for group '" << config.group << "' failed!"; return _SMERP::ErrorCodes::FAILURE; } if( setuid( passwdent->pw_uid ) < 0 ) { LOG_CRITICAL << "setgid for user '" << config.user << "' failed!"; return _SMERP::ErrorCodes::FAILURE; } // create a pid file and lock id std::ofstream pidFile( config.pidFile.c_str( ), std::ios_base::trunc ); if( !pidFile.good( ) ) { LOG_CRITICAL << "Unable to create PID file '" << config.pidFile << "'!"; return _SMERP::ErrorCodes::FAILURE; } pidFile << getpid( ) << std::endl; pidFile.close( ); // Create the final logger based on the configuration // file logger only here to get the right permissions _SMERP::LogBackend::instance().setLogfileLevel( config.logFileLogLevel ); _SMERP::LogBackend::instance().setLogfileName( config.logFile ); } // Block all signals for background thread. sigset_t new_mask; sigfillset( &new_mask ); sigset_t old_mask; pthread_sigmask( SIG_BLOCK, &new_mask, &old_mask ); LOG_NOTICE << "Starting server"; // Run server in background thread(s). _SMERP::ServerHandler handler( handlerConfig ); _SMERP::Network::server s( config.address, config.SSLaddress, handler, config.threads, config.maxConnections ); boost::thread t( boost::bind( &_SMERP::Network::server::run, &s )); // Restore previous signals. pthread_sigmask( SIG_SETMASK, &old_mask, 0 ); // Wait for signal indicating time to shut down. sigset_t wait_mask; sigemptyset( &wait_mask ); sigaddset( &wait_mask, SIGINT ); sigaddset( &wait_mask, SIGQUIT ); sigaddset( &wait_mask, SIGTERM ); pthread_sigmask( SIG_BLOCK, &wait_mask, 0 ); int sig = 0; sigwait( &wait_mask, &sig ); // Stop the server. LOG_INFO << "Stopping server"; s.stop(); t.join(); LOG_NOTICE << "Server stopped"; // Daemon stuff if( !config.foreground ) { (void)remove( config.pidFile.c_str( ) ); } } catch (std::exception& e) { // Aba: how to delete the pid file here? LOG_ERROR << "posixMain: exception: " << e.what() << "\n"; return _SMERP::ErrorCodes::FAILURE; } return _SMERP::ErrorCodes::OK; }
int main( int argc, char** argv ) { int err = 0; std::string argOutputDir; std::string symbolFile; std::string configFile; std::string password; bool printDebug; bool isLogging; int zero = 0; (void) signal(SIGINT, sighandler); (void) signal(SIGTERM, sighandler); (void) signal(SIGHUP, sighandler); g_zmq_context = zmq_init(1); assert(g_zmq_context); pub_socket = zmq_socket(g_zmq_context, ZMQ_PUB); zmq_setsockopt(pub_socket, ZMQ_LINGER, &zero, sizeof(zero)); assert(pub_socket); GOOGLE_PROTOBUF_VERIFY_VERSION; try { po::options_description desc("Allowed options"); desc.add_options() ("help", "produce help message") ("c", po::value<std::string>(), "<config file>") ("s", po::value<std::string>(), "<symbol file>") ("o", po::value<std::string>(), "<output path>") ("nolog", po::value<int>()->implicit_value(0), "disable logging (FIX and tick)") ("d", "debug info") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); if (vm.count("nolog")) { std::cout << "Logging disabled" << std::endl; //isLogging = (vm["nolog"].as<int>() == 1 ? false : true); isLogging = false; } else { std::cout << "Logging enabled" << std::endl; isLogging = true; } if (vm.count("help")) { std::cout << desc << "\n"; return 1; } if (vm.count("o")) { std::cout << "Output path: " << vm["o"].as<std::string>() << "\n"; argOutputDir = vm["o"].as<std::string>(); } else { // set default std::cout << "Output path file was not set \n"; } if (vm.count("s")) { std::cout << "Symbol file: " << vm["s"].as<std::string>() << "\n"; symbolFile = vm["s"].as<std::string>(); } else { // use default name for symbols file name symbolFile = "symbols.cfg"; std::cout << "Using default symbols file: symbols.cfg\n"; } if (vm.count("c")) { std::cout << "Config file: " << vm["c"].as<std::string>() << ".\n"; configFile = vm["c"].as<std::string>(); } else { std::cout << "Config file was not set.\n"; err++; } printDebug = vm.count("d") > 0; /* moved passwords to cfg files if (vm.count("p")) { std::cout << "Pass: "******"p"].as<std::string>() << ".\n"; password = vm["p"].as<std::string>(); } else { std::cout << "Password was not set.\n"; err++; } */ } catch(std::exception& e) { std::cerr << "EXCEPTION:" << e.what(); return 1; } if (err > 0) { std::cout << "Aborting due to missing parameters.\n"; return 1; } /* * @see http://www.boost.org/doc/libs/1_41_0/doc/html/program_options.html */ std::vector<std::string> symbols = readSymbols(symbolFile); try { FIX::SessionSettings settings(configFile); std::set<FIX::SessionID> sessions = settings.getSessions (); assert(sessions.size() == 1); FIX::SessionID sessionId = *(sessions.begin()); const FIX::Dictionary& dict = settings.get(sessionId); ApplicationConfig config; // MIC code for adding to output filename config.mic_string = dict.has("MIC") ? dict.getString("MIC") : ""; std::cout << "My MIC is: " << config.mic_string << std::endl; capk::get_config_params(g_zmq_context, "tcp://127.0.0.1:11111", &all_venue_config); capkproto::venue_configuration my_config = capk::get_venue_config(&all_venue_config, config.mic_string.c_str()); std::cout << "Received config:\n" << my_config.DebugString() << std::endl; // venue id as for protobuf usage to identify venue if (my_config.venue_id() == "") { std::cerr << "venue_id not set!" << std::endl; exit(-1); } else { // boost version of atoi if (qi::parse(my_config.venue_id().begin(), my_config.venue_id().end(), qi::int_, config.venue_id) == false) { std::cout << "Can't parse venue_id" << std::endl; exit(-1); } if (config.venue_id == 0) { std::cerr << "venue_id can not be 0" << std::endl; exit(-1); } std::cout << "Set venue_id to: " << config.venue_id << std::endl; } // Username and password settings config.username = dict.has("Username") ? dict.getString("Username") : ""; config.password = dict.has("Password") ? dict.getString("Password") : ""; config.sendPasswordInRawDataField = dict.has("SendPasswordInRawData") && dict.getBool("SendPasswordInRawData"); // Should use aggregated book? config.aggregatedBook = dict.has("AggregatedBook") && dict.getBool("AggregatedBook"); std::cout << "Aggregated book: " << config.aggregatedBook << std::endl; // Should we reset sequence numbers? bool bReset = dict.has("ResetSeqNo") && dict.getBool("ResetSeqNo"); std::cout << "Resetting sequence numbers: " << bReset << std::endl; // How to send market data requests - bulk or multiple messages config.sendIndividualMarketDataRequests = dict.has("SendIndividualMarketDataRequests") && dict.getBool("SendIndividualMarketDataRequests"); std::cout << "Send individual market data requests: " << config.sendIndividualMarketDataRequests << std::endl; // Fix Version string config.version = dict.has("FIXVersion") ? (FIXVersion)atoi(dict.getString("FIXVersion").c_str()) : FIX_42; std::cout << "Using FIX version: " << config.version << std::endl; // Market depth std::string depth = dict.has("MarketDepth") ? dict.getString("MarketDepth") : ""; config.marketDepth = atoi(depth.c_str()); std::cout << "Setting market depth: " << config.marketDepth << std::endl; // Update Type long updateType = dict.has("MDUpdateType") ? dict.getLong("MDUpdateType") : -1; std::cout << "Setting update type: " << updateType << std::endl; // Debug settings config.printDebug = printDebug; Application application(bReset, config); papplication = &application; application.addSymbols(symbols); // if user specified an output dir, then put files into date-sorted // subdirectories, otherwise put into the default dirs specified in // config file std::string orderBooksOutputDir = "."; std::string logOutputDir = dict.has("FileLogPath") ? dict.getString("FileLogPath") : "."; std::string storeOutputDir = dict.has("FileStorePath") ? dict.getString("FileStorePath") : "."; if (argOutputDir.length() > 0) { orderBooksOutputDir = argOutputDir; fs::path argPath = fs::path(argOutputDir); if (!fs::exists(argPath)) { fs::create_directories(argPath); } /* put both order books and message logs in subdirs, but put the store at the root dir */ fs::path logOutputPath = argPath / fs::path("log"); if (!fs::exists(logOutputPath)) { fs::create_directory(logOutputPath); } logOutputDir = logOutputPath.string(); fs::path storeOutputPath = argPath / fs::path("store"); if (!fs::exists(storeOutputPath)) { fs::create_directory(storeOutputPath); } storeOutputDir = storeOutputPath.string(); } pid_t pid = getpid(); pid_t ppid = getppid(); printf("pid: %d, ppid: %d\n", pid, ppid); std::string pidFileName = std::string(argv[0]) + "." + config.mic_string + std::string(".pid"); std::ofstream pidFile(pidFileName); if (pidFile.is_open()) { pidFile << pid; pidFile.flush(); } else { std::cerr << "Can't write pid file - exiting"; exit(-1); } // Get the bind address for zmq sockets bool isPublishing = dict.has("should_publish_prices") && dict.getBool("should_publish_prices"); if (isPublishing) { std::cout << "Collector is publishing prices to: " << my_config.market_data_broadcast_addr() << std::endl; } else { std::cout << "Collector is NOT publishing prices" << std::endl; } // ZMQ initialization if (isPublishing) { zmq_bind(pub_socket, my_config.market_data_broadcast_addr().c_str()); application.setZMQContext(g_zmq_context); application.setZMQSocket(pub_socket); } application.setPublishing(isPublishing); application.setLogging(isLogging); // Set MDUpdateType application.setUpdateType(updateType); // orderbook output setup application.setDataPath(orderBooksOutputDir); // fix logging params if (isLogging) { std::cout << "Logging with FileStoreFactory" << std::endl; FIX::FileStoreFactory fileStoreFactory(storeOutputDir); FIX::FileLogFactory logFactory(logOutputDir); pinitiator = new FIX::SocketInitiator(application, fileStoreFactory, settings, logFactory); } else { std::cout << "Logging with NullStoreFactory" << std::endl; FIX::NullStoreFactory nullStoreFactory; pinitiator = new FIX::SocketInitiator(application, nullStoreFactory, settings); } //pinitiator = &initiator; std::cout << "Starting initiator" << std::endl; pinitiator->start(); char x; while(std::cin >> x) { if (x == 'q') { break; } } std::cout << "Stopping initiator..." << std::endl; pinitiator->stop(); return 0; } catch ( FIX::Exception & e ) { std::cout << e.what(); return 1; } }