Server(FileDescriptor feedbackFd, const AgentOptions &_options) : options(_options), requestLoop(true), serverInstanceDir(options.webServerPid, options.tempDir, false), resourceLocator(options.passengerRoot) { TRACE_POINT(); this->feedbackFd = feedbackFd; UPDATE_TRACE_POINT(); generation = serverInstanceDir.getGeneration(options.generationNumber); startListening(); accountsDatabase = AccountsDatabase::createDefault(generation, options.userSwitching, options.defaultUser, options.defaultGroup); accountsDatabase->add("_web_server", options.messageSocketPassword, false, Account::EXIT); messageServer = ptr(new MessageServer(generation->getPath() + "/socket", accountsDatabase)); createFile(generation->getPath() + "/helper_agent.pid", toString(getpid()), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (geteuid() == 0 && !options.userSwitching) { lowerPrivilege(options.defaultUser, options.defaultGroup); } UPDATE_TRACE_POINT(); loggerFactory = make_shared<UnionStation::LoggerFactory>(options.loggingAgentAddress, "logging", options.loggingAgentPassword); randomGenerator = make_shared<RandomGenerator>(); spawnerFactory = make_shared<SpawnerFactory>(poolLoop.safe, resourceLocator, generation, randomGenerator); pool = make_shared<Pool>(poolLoop.safe.get(), spawnerFactory, loggerFactory, randomGenerator); pool->setMax(options.maxPoolSize); //pool->setMaxPerApp(maxInstancesPerApp); pool->setMaxIdleTime(options.poolIdleTime * 1000000); messageServer->addHandler(make_shared<RemoteController>(pool)); messageServer->addHandler(make_shared<BacktracesServer>()); messageServer->addHandler(ptr(new ExitHandler(exitEvent))); requestHandler = make_shared<RequestHandler>(requestLoop.safe, requestSocket, pool, options); sigquitWatcher.set(requestLoop.loop); sigquitWatcher.set(SIGQUIT); sigquitWatcher.set<Server, &Server::onSigquit>(this); sigquitWatcher.start(); UPDATE_TRACE_POINT(); writeArrayMessage(feedbackFd, "initialized", getRequestSocketFilename().c_str(), messageServer->getSocketFilename().c_str(), NULL); function<void ()> func = boost::bind(prestartWebApps, resourceLocator, options.prestartUrls ); prestarterThread = ptr(new oxt::thread( boost::bind(runAndPrintExceptions, func, true) )); }
Server(FileDescriptor feedbackFd, const AgentOptions &_options) : options(_options), requestLoop(true), serverInstanceDir(_options.serverInstanceDir, false), resourceLocator(options.passengerRoot) { TRACE_POINT(); this->feedbackFd = feedbackFd; UPDATE_TRACE_POINT(); generation = serverInstanceDir.getGeneration(options.generationNumber); startListening(); accountsDatabase = boost::make_shared<AccountsDatabase>(); accountsDatabase->add("_passenger-status", options.adminToolStatusPassword, false, Account::INSPECT_BASIC_INFO | Account::INSPECT_SENSITIVE_INFO | Account::INSPECT_BACKTRACES | Account::INSPECT_REQUESTS); accountsDatabase->add("_web_server", options.exitPassword, false, Account::EXIT); messageServer = boost::make_shared<MessageServer>( parseUnixSocketAddress(options.adminSocketAddress), accountsDatabase); createFile(generation->getPath() + "/helper_agent.pid", toString(getpid()), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (geteuid() == 0 && !options.userSwitching) { lowerPrivilege(options.defaultUser, options.defaultGroup); } UPDATE_TRACE_POINT(); randomGenerator = boost::make_shared<RandomGenerator>(); // Check whether /dev/urandom is actually random. // https://code.google.com/p/phusion-passenger/issues/detail?id=516 if (randomGenerator->generateByteString(16) == randomGenerator->generateByteString(16)) { throw RuntimeException("Your random number device, /dev/urandom, appears to be broken. " "It doesn't seem to be returning random data. Please fix this."); } UPDATE_TRACE_POINT(); loggerFactory = boost::make_shared<UnionStation::LoggerFactory>(options.loggingAgentAddress, "logging", options.loggingAgentPassword); spawnerFactory = boost::make_shared<SpawnerFactory>(poolLoop.safe, resourceLocator, generation, boost::make_shared<SpawnerConfig>(randomGenerator)); pool = boost::make_shared<Pool>(poolLoop.safe.get(), spawnerFactory, loggerFactory, randomGenerator); pool->initialize(); pool->setMax(options.maxPoolSize); //pool->setMaxPerApp(maxInstancesPerApp); pool->setMaxIdleTime(options.poolIdleTime * 1000000); requestHandler = boost::make_shared<RequestHandler>(requestLoop.safe, requestSocket, pool, options); messageServer->addHandler(boost::make_shared<RemoteController>(requestHandler, pool)); messageServer->addHandler(ptr(new ExitHandler(exitEvent))); sigquitWatcher.set(requestLoop.loop); sigquitWatcher.set(SIGQUIT); sigquitWatcher.set<Server, &Server::onSigquit>(this); sigquitWatcher.start(); UPDATE_TRACE_POINT(); writeArrayMessage(feedbackFd, "initialized", getRequestSocketFilename().c_str(), messageServer->getSocketFilename().c_str(), NULL); boost::function<void ()> func = boost::bind(prestartWebApps, resourceLocator, options.defaultRubyCommand, options.prestartUrls ); prestarterThread = ptr(new oxt::thread( boost::bind(runAndPrintExceptions, func, true) )); }
Server(FileDescriptor feedbackFd, pid_t webServerPid, const string &tempDir, bool userSwitching, const string &defaultUser, const string &defaultGroup, const string &passengerRoot, const string &rubyCommand, unsigned int generationNumber, unsigned int maxPoolSize, unsigned int maxInstancesPerApp, unsigned int poolIdleTime, const VariantMap &options) : serverInstanceDir(webServerPid, tempDir, false), resourceLocator(passengerRoot) { TRACE_POINT(); string messageSocketPassword; string loggingAgentPassword; this->feedbackFd = feedbackFd; feedbackChannel = MessageChannel(feedbackFd); UPDATE_TRACE_POINT(); messageSocketPassword = Base64::decode(options.get("message_socket_password")); loggingAgentPassword = options.get("logging_agent_password"); generation = serverInstanceDir.getGeneration(generationNumber); accountsDatabase = AccountsDatabase::createDefault(generation, userSwitching, defaultUser, defaultGroup); accountsDatabase->add("_web_server", messageSocketPassword, false, Account::GET | Account::DETACH | Account::SET_PARAMETERS | Account::EXIT); messageServer = ptr(new MessageServer(generation->getPath() + "/socket", accountsDatabase)); createFile(generation->getPath() + "/helper_server.pid", toString(getpid()), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (geteuid() == 0 && !userSwitching) { lowerPrivilege(defaultUser, defaultGroup); } UPDATE_TRACE_POINT(); analyticsLogger = ptr(new AnalyticsLogger(options.get("logging_agent_address"), "logging", loggingAgentPassword)); pool = ptr(new ApplicationPool::Pool( resourceLocator.getSpawnServerFilename(), generation, accountsDatabase, rubyCommand, analyticsLogger, options.getInt("log_level"), options.get("debug_log_file", false) )); pool->setMax(maxPoolSize); pool->setMaxPerApp(maxInstancesPerApp); pool->setMaxIdleTime(poolIdleTime); messageServer->addHandler(ptr(new TimerUpdateHandler(exitTimer))); messageServer->addHandler(ptr(new ApplicationPool::Server(pool))); messageServer->addHandler(ptr(new BacktracesServer())); messageServer->addHandler(ptr(new ExitHandler(exitEvent))); UPDATE_TRACE_POINT(); feedbackChannel.write("initialized", "", // Request socket filename; not available in the Apache helper server. messageServer->getSocketFilename().c_str(), NULL); prestarterThread = ptr(new oxt::thread( boost::bind(prestartWebApps, resourceLocator, options.get("prestart_urls")) )); }