mirror of https://github.com/KLayout/klayout.git
Avoid a deadlock in the logger system
This commit is contained in:
parent
536681f5e1
commit
fa1719acc3
|
|
@ -84,6 +84,12 @@ LogReceiver::endl ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LogReceiver::yield ()
|
||||||
|
{
|
||||||
|
mp_file->yield ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogReceiver::end ()
|
LogReceiver::end ()
|
||||||
{
|
{
|
||||||
|
|
@ -223,30 +229,36 @@ LogFile::max_entries () const
|
||||||
|
|
||||||
void
|
void
|
||||||
LogFile::add (LogFileEntry::mode_type mode, const std::string &msg, bool continued)
|
LogFile::add (LogFileEntry::mode_type mode, const std::string &msg, bool continued)
|
||||||
|
{
|
||||||
|
QMutexLocker locker (&m_lock);
|
||||||
|
|
||||||
|
if (m_max_entries == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_messages.size () >= m_max_entries) {
|
||||||
|
m_messages.pop_front ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == LogFileEntry::Warning || mode == LogFileEntry::WarningContinued) {
|
||||||
|
m_has_warnings = true;
|
||||||
|
} else if (mode == LogFileEntry::Error || mode == LogFileEntry::ErrorContinued) {
|
||||||
|
m_has_errors = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_messages.push_back (LogFileEntry (mode, msg, continued));
|
||||||
|
|
||||||
|
++m_generation_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LogFile::yield ()
|
||||||
{
|
{
|
||||||
bool can_yield = false;
|
bool can_yield = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
QMutexLocker locker (&m_lock);
|
QMutexLocker locker (&m_lock);
|
||||||
|
|
||||||
if (m_max_entries == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_messages.size () >= m_max_entries) {
|
|
||||||
m_messages.pop_front ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == LogFileEntry::Warning || mode == LogFileEntry::WarningContinued) {
|
|
||||||
m_has_warnings = true;
|
|
||||||
} else if (mode == LogFileEntry::Error || mode == LogFileEntry::ErrorContinued) {
|
|
||||||
m_has_errors = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_messages.push_back (LogFileEntry (mode, msg, continued));
|
|
||||||
|
|
||||||
++m_generation_id;
|
|
||||||
|
|
||||||
if (lay::ApplicationBase::instance ()->qapp_gui () && QThread::currentThread () == lay::ApplicationBase::instance ()->qapp_gui ()->thread () && (tl::Clock::current () - m_last_yield).seconds () > 0.1) {
|
if (lay::ApplicationBase::instance ()->qapp_gui () && QThread::currentThread () == lay::ApplicationBase::instance ()->qapp_gui ()->thread () && (tl::Clock::current () - m_last_yield).seconds () > 0.1) {
|
||||||
m_last_yield = tl::Clock::current ();
|
m_last_yield = tl::Clock::current ();
|
||||||
can_yield = true;
|
can_yield = true;
|
||||||
|
|
@ -254,6 +266,9 @@ LogFile::add (LogFileEntry::mode_type mode, const std::string &msg, bool continu
|
||||||
}
|
}
|
||||||
|
|
||||||
// use this opportunity to process events
|
// use this opportunity to process events
|
||||||
|
// NOTE: as process events may trigger further log output, it's necessary to do process events outside any other
|
||||||
|
// method (e.g. add) which is subject to locking. Hence we avoid deadlocks.
|
||||||
|
// We accept the risk of recursion inside process_events as we have a timeout before accepting new yield calls.
|
||||||
if (can_yield) {
|
if (can_yield) {
|
||||||
lay::ApplicationBase::instance ()->process_events (QEventLoop::AllEvents);
|
lay::ApplicationBase::instance ()->process_events (QEventLoop::AllEvents);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ protected:
|
||||||
virtual void endl ();
|
virtual void endl ();
|
||||||
virtual void end ();
|
virtual void end ();
|
||||||
virtual void begin ();
|
virtual void begin ();
|
||||||
|
virtual void yield ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LogFile *mp_file;
|
LogFile *mp_file;
|
||||||
|
|
@ -193,6 +194,11 @@ public slots:
|
||||||
return m_log_receiver;
|
return m_log_receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implementation of post-log action
|
||||||
|
*/
|
||||||
|
void yield ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the maximum number of entries to show
|
* @brief Sets the maximum number of entries to show
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1112,6 +1112,7 @@ protected:
|
||||||
virtual void endl () { mp_rec->errlog_endl (); }
|
virtual void endl () { mp_rec->errlog_endl (); }
|
||||||
virtual void end () { mp_rec->errlog_end (); }
|
virtual void end () { mp_rec->errlog_end (); }
|
||||||
virtual void begin () { mp_rec->errlog_begin (); }
|
virtual void begin () { mp_rec->errlog_begin (); }
|
||||||
|
virtual void yield () { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Recorder *mp_rec;
|
Recorder *mp_rec;
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,9 @@ Channel::release_proxy ()
|
||||||
m_active = false;
|
m_active = false;
|
||||||
m_no_endl = false;
|
m_no_endl = false;
|
||||||
m_lock.unlock ();
|
m_lock.unlock ();
|
||||||
|
|
||||||
|
// after we have released the lock we give the receivers an opportunity to process events
|
||||||
|
yield ();
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelEndl endl;
|
ChannelEndl endl;
|
||||||
|
|
@ -160,6 +163,18 @@ LogTee::puts (const char *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LogTee::yield ()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
for (tl::weak_collection<tl::Channel>::iterator c = m_channels.begin (); c != m_channels.end (); ++c) {
|
||||||
|
c->yield ();
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
// ignore exceptions here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogTee::endl ()
|
LogTee::endl ()
|
||||||
{
|
{
|
||||||
|
|
@ -270,6 +285,7 @@ protected:
|
||||||
virtual void endl ();
|
virtual void endl ();
|
||||||
virtual void end ();
|
virtual void end ();
|
||||||
virtual void begin ();
|
virtual void begin ();
|
||||||
|
virtual void yield () { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_verbosity;
|
int m_verbosity;
|
||||||
|
|
@ -342,6 +358,7 @@ protected:
|
||||||
virtual void endl ();
|
virtual void endl ();
|
||||||
virtual void end ();
|
virtual void end ();
|
||||||
virtual void begin ();
|
virtual void begin ();
|
||||||
|
virtual void yield () { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_colorized;
|
bool m_colorized;
|
||||||
|
|
@ -406,6 +423,7 @@ protected:
|
||||||
virtual void endl ();
|
virtual void endl ();
|
||||||
virtual void end ();
|
virtual void end ();
|
||||||
virtual void begin ();
|
virtual void begin ();
|
||||||
|
virtual void yield () { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_colorized;
|
bool m_colorized;
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ protected:
|
||||||
virtual void endl () = 0;
|
virtual void endl () = 0;
|
||||||
virtual void end () = 0;
|
virtual void end () = 0;
|
||||||
virtual void begin () = 0;
|
virtual void begin () = 0;
|
||||||
|
virtual void yield () = 0;
|
||||||
|
|
||||||
tl::Mutex m_lock;
|
tl::Mutex m_lock;
|
||||||
|
|
||||||
|
|
@ -265,6 +266,7 @@ protected:
|
||||||
virtual void endl ();
|
virtual void endl ();
|
||||||
virtual void end ();
|
virtual void end ();
|
||||||
virtual void begin ();
|
virtual void begin ();
|
||||||
|
virtual void yield ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
tl::weak_collection<tl::Channel> m_channels;
|
tl::weak_collection<tl::Channel> m_channels;
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,7 @@ protected:
|
||||||
virtual void endl ();
|
virtual void endl ();
|
||||||
virtual void end ();
|
virtual void end ();
|
||||||
virtual void begin ();
|
virtual void begin ();
|
||||||
|
virtual void yield () { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostringstream m_text;
|
std::ostringstream m_text;
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ protected:
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void yield () { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_verbosity;
|
int m_verbosity;
|
||||||
};
|
};
|
||||||
|
|
@ -108,6 +110,8 @@ protected:
|
||||||
{
|
{
|
||||||
TestConsole::instance ()->begin_warn ();
|
TestConsole::instance ()->begin_warn ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void yield () { }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ErrorChannel : public tl::Channel
|
class ErrorChannel : public tl::Channel
|
||||||
|
|
@ -139,6 +143,8 @@ protected:
|
||||||
{
|
{
|
||||||
TestConsole::instance ()->begin_error ();
|
TestConsole::instance ()->begin_error ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void yield () { }
|
||||||
};
|
};
|
||||||
|
|
||||||
class CtrlChannel : public tl::Channel
|
class CtrlChannel : public tl::Channel
|
||||||
|
|
@ -180,6 +186,8 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void yield () { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_with_xml;
|
bool m_with_xml;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue