From 098f8b6684cb74e252fd89b177886424d439ca9e Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 9 Jan 2013 09:50:53 +0100 Subject: [PATCH] Backend logs are not created using 'backend-N.log' pattern where N is ID of the backend (1, 2, 3, 4, ...) according to the backends number --- include/transport/networkpluginserver.h | 2 + spectrum/src/backend-logging.cfg | 4 +- src/config.cpp | 2 +- src/logging.cpp | 11 +++- src/networkpluginserver.cpp | 87 +++++++++++++++++++++++-- 5 files changed, 96 insertions(+), 10 deletions(-) diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 738a0cc8..b5aa0b71 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -136,6 +136,7 @@ class NetworkPluginServer { void handleFTRejected(User *user, const std::string &buddyName, const std::string &fileName, unsigned long size); void handleFTDataNeeded(Backend *b, unsigned long ftid); + void handlePIDTerminated(unsigned long pid); private: void send(boost::shared_ptr &, const std::string &data); @@ -152,6 +153,7 @@ class NetworkPluginServer { Config *m_config; boost::shared_ptr m_server; std::list m_clients; + std::vector m_pids; Swift::Timer::ref m_pingTimer; Swift::Timer::ref m_collectTimer; Swift::Timer::ref m_loginTimer; diff --git a/spectrum/src/backend-logging.cfg b/spectrum/src/backend-logging.cfg index fcdc906c..1078afe2 100644 --- a/spectrum/src/backend-logging.cfg +++ b/spectrum/src/backend-logging.cfg @@ -1,11 +1,11 @@ log4j.rootLogger=debug, R log4j.appender.R=org.apache.log4j.RollingFileAppender -log4j.appender.R.File=/var/log/spectrum2/${jid}/backends/backend-${pid}.log +log4j.appender.R.File=/var/log/spectrum2/${jid}/backends/backend-${id}.log log4j.appender.R.MaxFileSize=10000KB # Keep one backup file log4j.appender.R.MaxBackupIndex=1 log4j.appender.R.layout=org.apache.log4j.PatternLayout -log4j.appender.R.layout.ConversionPattern=%d %-5p %c: %m%n +log4j.appender.R.layout.ConversionPattern=${pid}: %d %-5p %c: %m%n diff --git a/src/config.cpp b/src/config.cpp index 8873c862..a30a01e1 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -363,7 +363,7 @@ Config *Config::createFromArgs(int argc, char **argv, std::string &error, std::s } catch (std::runtime_error& e) { - error = os.str(); + error = std::string(e.what()) + "\n" + os.str(); return NULL; } catch (...) diff --git a/src/logging.cpp b/src/logging.cpp index a7f8478b..e2433e34 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -119,24 +119,29 @@ static void initLogging(Config *config, std::string key) { } p.load(istream); - LogString pid, jid; + LogString pid, jid, id; log4cxx::helpers::Transcoder::decode(boost::lexical_cast(getpid()), pid); log4cxx::helpers::Transcoder::decode(CONFIG_STRING(config, "service.jid"), jid); + log4cxx::helpers::Transcoder::decode(CONFIG_STRING_DEFAULTED(config, "service.backend_id", ""), id); #ifdef _MSC_VER p.setProperty(L"pid", pid); p.setProperty(L"jid", jid); + p.setProperty(L"id", id); #else p.setProperty("pid", pid); p.setProperty("jid", jid); + p.setProperty("id", id); #endif std::string dir; BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) { - if (boost::ends_with(prop, ".File")) { +// if (boost::ends_with(prop, ".File")) { log4cxx::helpers::Transcoder::encode(p.get(prop), dir); boost::replace_all(dir, "${jid}", jid); + boost::replace_all(dir, "${pid}", pid); + boost::replace_all(dir, "${id}", id); break; - } +// } } mode_t old_cmask; if (!dir.empty()) { diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 8e80e321..cd3734b8 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -71,6 +71,8 @@ static unsigned long bytestream_id; DEFINE_LOGGER(logger, "NetworkPluginServer"); +static NetworkPluginServer *_server; + class NetworkConversation : public Conversation { public: NetworkConversation(ConversationManager *conversationManager, const std::string &legacyName, bool muc = false) : Conversation(conversationManager, legacyName, muc) { @@ -128,7 +130,7 @@ class NetworkFactory : public Factory { wrap.SerializeToString(&MESSAGE); // Executes new backend -static unsigned long exec_(const std::string& exePath, const char *host, const char *port, const char *cmdlineArgs) { +static unsigned long exec_(const std::string& exePath, const char *host, const char *port, const char *log_id, const char *cmdlineArgs) { // BACKEND_ID is replaced with unique ID. The ID is increasing for every backend. std::string finalExePath = boost::replace_all_copy(exePath, "BACKEND_ID", boost::lexical_cast(backend_id++)); @@ -171,7 +173,7 @@ static unsigned long exec_(const std::string& exePath, const char *host, const c return 0; #else // Add host and port. - finalExePath += std::string(" --host ") + host + " --port " + port + " " + cmdlineArgs; + finalExePath += std::string(" --host ") + host + " --port " + port + " --service.backend_id=" + log_id + " " + cmdlineArgs; LOG4CXX_INFO(logger, "Starting new backend " << finalExePath); // Create array of char * from string using -lpopt library @@ -214,6 +216,7 @@ static void SigCatcher(int n) { // WARNING: Do not put LOG4CXX_ here, because it can lead to deadlock while ((result = waitpid(-1, &status, WNOHANG)) > 0) { if (result != 0) { + _server->handlePIDTerminated((unsigned long)result); if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) { // LOG4CXX_ERROR(logger, "Backend can not be started, exit_code=" << WEXITSTATUS(status)); @@ -251,6 +254,7 @@ static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payloa } NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager, DiscoItemsResponder *discoItemsResponder) { + _server = this; m_ftManager = ftManager; m_userManager = userManager; m_config = config; @@ -324,7 +328,7 @@ void NetworkPluginServer::start() { LOG4CXX_INFO(logger, "Listening on host " << CONFIG_STRING(m_config, "service.backend_host") << " port " << CONFIG_STRING(m_config, "service.backend_port")); while (true) { - unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getCommandLineArgs().c_str()); + unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), "1", m_config->getCommandLineArgs().c_str()); LOG4CXX_INFO(logger, "Tried to spawn first backend with pid " << pid); LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects"); @@ -353,6 +357,8 @@ void NetworkPluginServer::start() { } } + m_pids.push_back(pid); + signal(SIGCHLD, SigCatcher); #endif // quit the while loop @@ -1660,6 +1666,57 @@ void NetworkPluginServer::sendPing(Backend *c) { // LOG4CXX_INFO(logger, "PING to " << c); } +void NetworkPluginServer::handlePIDTerminated(unsigned long pid) { + std::vector::iterator log_id_it; + log_id_it = std::find(m_pids.begin(), m_pids.end(), pid); + if (log_id_it != m_pids.end()) { + *log_id_it = 0; + } +} + +#ifndef _WIN32 + +static int sig_block_count = 0; +static sigset_t block_mask; + +static void __block_signals ( void ) +{ + static int init_done = 0; + + if ( (sig_block_count++) != 1 ) return; + + if ( init_done == 0 ) { + sigemptyset ( &block_mask ); + sigaddset ( &block_mask, SIGPIPE ); + sigaddset ( &block_mask, SIGHUP ); + sigaddset ( &block_mask, SIGINT ); + sigaddset ( &block_mask, SIGQUIT ); + sigaddset ( &block_mask, SIGTERM ); + sigaddset ( &block_mask, SIGABRT ); + sigaddset ( &block_mask, SIGCHLD ); + init_done = 1; + } + + sigprocmask ( SIG_BLOCK, &block_mask, NULL ); + return; +} + +static void __unblock_signals ( void ) +{ + sigset_t sigset; + + if ( (sig_block_count--) != 0 ) return; + sigprocmask ( SIG_UNBLOCK, &block_mask, NULL ); + + if ( sigpending ( &sigset ) == 0 ) { + if ( sigismember ( &sigset, SIGCHLD ) ) { + raise ( SIGCHLD ); + } + } +} + +#endif + NetworkPluginServer::Backend *NetworkPluginServer::getFreeClient(bool acceptUsers, bool longRun, bool check) { NetworkPluginServer::Backend *c = NULL; @@ -1692,7 +1749,29 @@ NetworkPluginServer::Backend *NetworkPluginServer::getFreeClient(bool acceptUser if (c == NULL && !m_startingBackend) { m_isNextLongRun = longRun; m_startingBackend = true; - exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getCommandLineArgs().c_str()); + +#ifndef _WIN32 + __block_signals(); +#endif + std::vector::iterator log_id_it; + log_id_it = std::find(m_pids.begin(), m_pids.end(), 0); + std::string log_id = ""; + if (log_id_it == m_pids.end()) { + log_id = boost::lexical_cast(m_pids.size() + 1); + } + else { + log_id = boost::lexical_cast(log_id_it - m_pids.begin() + 1); + } + unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), log_id.c_str(), m_config->getCommandLineArgs().c_str()); + if (log_id_it == m_pids.end()) { + m_pids.push_back(pid); + } + else { + *log_id_it = pid; + } +#ifndef _WIN32 + __unblock_signals(); +#endif } return c;