Permalink
Browse files

Make mythlogserver shutdown quickly if the socket's used already

I had some deadlocks with the startup of logging and the shutdown.  This now
seems to behave correctly.
  • Loading branch information...
Beirdo committed Jun 30, 2012
1 parent b571874 commit d553247877aad709257f684a792f26133c12729c
@@ -303,6 +303,7 @@ void LoggerThread::run(void)
LOG(VB_GENERAL, LOG_INFO, "Added logging to the console");
+ bool dieNow = false;
try
{
if (m_locallogs)
@@ -316,41 +317,55 @@ void LoggerThread::run(void)
m_zmqContext->start();
}
- qRegisterMetaType<QList<QByteArray> >("QList<QByteArray>");
+ if (!m_zmqContext)
+ {
+ m_aborted = true;
+ dieNow = true;
+ }
+ else
+ {
+ qRegisterMetaType<QList<QByteArray> >("QList<QByteArray>");
- m_zmqSocket = m_zmqContext->createSocket(nzmqt::ZMQSocket::TYP_DEALER,
- this);
- connect(m_zmqSocket, SIGNAL(messageReceived(const QList<QByteArray>&)),
- SLOT(messageReceived(const QList<QByteArray>&)),
- Qt::QueuedConnection);
+ m_zmqSocket =
+ m_zmqContext->createSocket(nzmqt::ZMQSocket::TYP_DEALER, this);
+ connect(m_zmqSocket,
+ SIGNAL(messageReceived(const QList<QByteArray>&)),
+ SLOT(messageReceived(const QList<QByteArray>&)),
+ Qt::QueuedConnection);
- if (m_locallogs)
- m_zmqSocket->connectTo("inproc://mylogs");
- else
- m_zmqSocket->connectTo("tcp://127.0.0.1:35327");
+ if (m_locallogs)
+ m_zmqSocket->connectTo("inproc://mylogs");
+ else
+ m_zmqSocket->connectTo("tcp://127.0.0.1:35327");
+ }
}
catch (nzmqt::ZMQException &e)
{
cerr << "Exception during logging socket setup: " << e.what() << endl;
- qApp->quit();
+ m_aborted = true;
+ dieNow = true;
}
- if (!m_locallogs)
+ if (!m_aborted)
{
- m_initialWaiting = true;
- pingLogServer();
+ if (!m_locallogs)
+ {
+ m_initialWaiting = true;
+ pingLogServer();
- // wait up to 150ms for mythlogserver to respond
- m_initialTimer = new MythSignalingTimer(this, SLOT(initialTimeout()));
- m_initialTimer->start(150);
- }
- else
- LOG(VB_GENERAL, LOG_INFO, "Added logging to mythlogserver locally");
+ // wait up to 150ms for mythlogserver to respond
+ m_initialTimer = new MythSignalingTimer(this,
+ SLOT(initialTimeout()));
+ m_initialTimer->start(150);
+ }
+ else
+ LOG(VB_GENERAL, LOG_INFO, "Added logging to mythlogserver locally");
- loggingGetTimeStamp(&m_epoch, NULL);
-
- m_heartbeatTimer = new MythSignalingTimer(this, SLOT(checkHeartBeat()));
- m_heartbeatTimer->start(1000);
+ loggingGetTimeStamp(&m_epoch, NULL);
+
+ m_heartbeatTimer = new MythSignalingTimer(this, SLOT(checkHeartBeat()));
+ m_heartbeatTimer->start(1000);
+ }
QMutexLocker qLock(&logQueueMutex);
@@ -379,23 +394,34 @@ void LoggerThread::run(void)
qLock.relock();
}
+ qLock.unlock();
+
// This must be before the timer stop below or we deadlock when the timer
// thread tries to deregister, and we wait for it.
logThreadFinished = true;
- m_heartbeatTimer->stop();
- delete m_heartbeatTimer;
- m_heartbeatTimer = NULL;
+ if (m_heartbeatTimer)
+ {
+ m_heartbeatTimer->stop();
+ delete m_heartbeatTimer;
+ m_heartbeatTimer = NULL;
+ }
- m_zmqSocket->setLinger(0);
- m_zmqSocket->close();
+ if (m_zmqSocket)
+ {
+ m_zmqSocket->setLinger(0);
+ m_zmqSocket->close();
+ }
if (!m_locallogs)
delete m_zmqContext;
- qLock.unlock();
-
RunEpilog();
+
+ if (dieNow)
+ {
+ qApp->processEvents();
+ }
}
/// \brief Handles the initial startup timeout when waiting for the log server
@@ -541,7 +567,7 @@ void LoggerThread::handleItem(LoggingItem *item)
if (item->m_message[0] != '\0')
{
// Send it to mythlogserver
- if (!logThreadFinished)
+ if (!logThreadFinished && m_zmqSocket)
m_zmqSocket->sendMessage(item->toByteArray());
}
}
@@ -63,6 +63,7 @@ LogForwardThread *logForwardThread = NULL;
static QMutex logThreadStartedMutex;
static QWaitCondition logThreadStarted;
static bool logThreadFinished = false;
+static bool logThreadStarting = false;
typedef QList<LoggerBase *> LoggerList;
@@ -791,6 +792,7 @@ void LogServerThread::run(void)
ctx->setInterval(100);
ctx->start();
+ bool abortThread = false;
try
{
m_zmqInSock = m_zmqContext->createSocket(nzmqt::ZMQSocket::TYP_ROUTER);
@@ -804,43 +806,64 @@ void LogServerThread::run(void)
{
LOG(VB_GENERAL, LOG_ERR, QString("Exception during socket setup: %1")
.arg(e.what()));
- qApp->quit();
+ abortThread = true;
}
+ if (!abortThread)
+ {
+ logForwardThread = new LogForwardThread();
+ logForwardThread->start();
- logForwardThread = new LogForwardThread();
- logForwardThread->start();
+ connect(logForwardThread, SIGNAL(pingClient(QString)),
+ this, SLOT(pingClient(QString)), Qt::QueuedConnection);
- connect(logForwardThread, SIGNAL(pingClient(QString)),
- this, SLOT(pingClient(QString)), Qt::QueuedConnection);
+ // cerr << "wake all" << endl;
+ locker.unlock();
+ logThreadStarted.wakeAll();
+ // cerr << "unlock" << endl;
- // cerr << "wake all" << endl;
- locker.unlock();
- logThreadStarted.wakeAll();
- // cerr << "unlock" << endl;
-
- msgsSinceHeartbeat = 0;
- m_heartbeatTimer = new MythSignalingTimer(this, SLOT(checkHeartBeats()));
- m_heartbeatTimer->start(1000);
+ msgsSinceHeartbeat = 0;
+ m_heartbeatTimer = new MythSignalingTimer(this,
+ SLOT(checkHeartBeats()));
+ m_heartbeatTimer->start(1000);
- exec();
+ exec();
+ }
logThreadFinished = true;
- m_heartbeatTimer->stop();
- delete m_heartbeatTimer;
+ if (m_heartbeatTimer)
+ {
+ m_heartbeatTimer->stop();
+ delete m_heartbeatTimer;
+ }
- m_zmqInSock->setLinger(0);
- m_zmqInSock->close();
+ if (m_zmqInSock)
+ {
+ m_zmqInSock->setLinger(0);
+ m_zmqInSock->close();
+ }
if (logForwardThread)
+ {
logForwardThread->stop();
- delete logForwardThread;
- logForwardThread = NULL;
+ delete logForwardThread;
+ logForwardThread = NULL;
+ }
delete m_zmqContext;
+ m_zmqContext = NULL;
RunEpilog();
+
+ if (abortThread)
+ {
+ // cerr << "wake all" << endl;
+ locker.unlock();
+ logThreadStarted.wakeAll();
+ qApp->processEvents();
+ // cerr << "unlock" << endl;
+ }
}
/// \brief Sends a ping message to the given client
@@ -923,20 +946,26 @@ void LogServerThread::stop(void)
/// \param dblog true if database logging is requested
/// \param propagate true if the logfile path needs to be propagated to child
/// processes.
-void logServerStart(void)
+/// \return TRUE on success, FALSE on failure
+bool logServerStart(void)
{
if (logServerThread && logServerThread->isRunning())
- return;
+ return true;
if (!logServerThread)
logServerThread = new LogServerThread();
+ logThreadStarting = true;
+
// cerr << "starting server" << endl;
QMutexLocker locker(&logThreadStartedMutex);
logServerThread->start();
logThreadStarted.wait(locker.mutex());
locker.unlock();
// cerr << "done starting server" << endl;
+
+ usleep(10000);
+ return (logServerThread && logServerThread->isRunning());
}
/// \brief Entry point for stopping logging for an application
@@ -960,7 +989,9 @@ void logServerWait(void)
{
// cerr << "waiting" << endl;
QMutexLocker locker(&logThreadStartedMutex);
- logThreadStarted.wait(locker.mutex());
+ while (!logThreadStarting ||
+ (logServerThread && logServerThread->isRunning()))
+ logThreadStarted.wait(locker.mutex(), 100);
locker.unlock();
// cerr << "done waiting" << endl;
}
@@ -23,7 +23,7 @@ class QString;
class MSqlQuery;
class LoggingItem;
-MBASE_PUBLIC void logServerStart(void);
+MBASE_PUBLIC bool logServerStart(void);
MBASE_PUBLIC void logServerStop(void);
void logServerWait(void);
@@ -28,8 +28,12 @@ namespace {
{
logStop();
logServerStop();
- delete gContext;
- gContext = NULL;
+
+ if (gContext)
+ {
+ delete gContext;
+ gContext = NULL;
+ }
}
class CleanupGuard
@@ -85,14 +89,19 @@ int main(int argc, char *argv[])
if ((retval = cmdline.ConfigureLogging(mask, daemonize)) != GENERIC_EXIT_OK)
return retval;
- logServerStart();
+ bool logging = logServerStart();
if (daemonize)
// Don't listen to console input if daemonized
close(0);
+ gContext = NULL;
+
CleanupGuard callCleanup(cleanup);
+ if (!logging)
+ return GENERIC_EXIT_OK;
+
#ifndef _WIN32
QList<int> signallist;
signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE

0 comments on commit d553247

Please sign in to comment.