Advertising
- Someone
- Monday, June 18th, 2012 at 7:01:44am MDT
- commit 2f608673c2bd90dd66c38e78c51b81cd1535bda5
- Author: Stuart Morgan <smorgan@mythtv.org>
- Date: Mon Jun 18 14:00:43 2012 +0100
- Split the scheduler lock into two, one protecting the reschedule queue and the other everything else. Attempts to fix a deadlock in mythbackend caused when the EIT scanner requests a reschedule immedately prior to a recording starting. The recorder thread locks the scheduler before requesting the EIT scanner to stop which leads to a race condition. The reschedule request from the scanner is handled in the backend event loop and waits for the scheduler lock to be released, the event loop is now stopped from handling any further events, meanwhile the recorder is waiting on events to be processed before it will release the lock resulting in a deadlock and the failure of the recording.
- diff --git a/mythtv/programs/mythbackend/scheduler.cpp b/mythtv/programs/mythbackend/scheduler.cpp
- index fd90548..74237f0 100644
- --- a/mythtv/programs/mythbackend/scheduler.cpp
- +++ b/mythtv/programs/mythbackend/scheduler.cpp
- @@ -59,6 +59,7 @@ Scheduler::Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
- recordTable(tmptable),
- priorityTable("powerpriority"),
- schedLock(),
- + m_queueLock(),
- reclist_changed(false),
- specsched(master_sched),
- schedMoveHigher(false),
- @@ -1633,7 +1634,7 @@ void Scheduler::GetAllScheduled(QStringList &strList)
- void Scheduler::Reschedule(const QStringList &request)
- {
- - QMutexLocker locker(&schedLock);
- + QMutexLocker locker(&m_queueLock);
- reschedQueue.enqueue(request);
- reschedWait.wakeOne();
- }
- @@ -1778,11 +1779,11 @@ void Scheduler::run(void)
- // wait for slaves to connect
- sleep(3);
- - QMutexLocker lockit(&schedLock);
- -
- - reschedQueue.clear();
- + ClearRequestQueue();
- EnqueueMatch(0, 0, 0, QDateTime(), "SchedulerInit");
- + QMutexLocker lockit(&schedLock);
- +
- int prerollseconds = 0;
- int wakeThreshold = 300;
- int idleTimeoutSecs = 0;
- @@ -1820,7 +1821,7 @@ void Scheduler::run(void)
- }
- else
- {
- - if (reschedQueue.empty())
- + if (!HaveQueuedRequests())
- {
- int sched_sleep = (secs_to_next - schedRunTime - 1) * 1000;
- sched_sleep = min(sched_sleep, maxSleep);
- @@ -1833,9 +1834,9 @@ void Scheduler::run(void)
- if (!doRun)
- break;
- }
- -
- +
- QTime t; t.start();
- - if (!reschedQueue.empty() && HandleReschedule())
- + if (HaveQueuedRequests() && HandleReschedule())
- {
- statuschanged = true;
- startIter = reclist.begin();
- @@ -1853,6 +1854,7 @@ void Scheduler::run(void)
- tuningTimeout =
- gCoreContext->GetNumSetting("tuningTimeout", 180);
- }
- +
- int e = t.elapsed();
- if (e > 0)
- {
- @@ -2093,10 +2095,12 @@ bool Scheduler::HandleReschedule(void)
- QString msg;
- bool deleteFuture = false;
- bool runCheck = false;
- -
- - while (!reschedQueue.empty())
- +
- + while (HaveQueuedRequests())
- {
- + m_queueLock.lock();
- QStringList request = reschedQueue.dequeue();
- + m_queueLock.unlock();
- QStringList tokens;
- if (request.size() >= 1)
- tokens = request[0].split(' ', QString::SkipEmptyParts);
- @@ -5162,4 +5166,37 @@ bool Scheduler::WasStartedAutomatically()
- return autoStart;
- }
- +void Scheduler::EnqueueMatch(uint recordid, uint sourceid, uint mplexid,
- + const QDateTime maxstarttime, const QString &why)
- +{
- + QMutexLocker locker(&m_queueLock);
- + reschedQueue.enqueue(ScheduledRecording::BuildMatchRequest(recordid,
- + sourceid, mplexid, maxstarttime, why));
- +}
- +
- +void Scheduler::EnqueueCheck(const RecordingInfo &recinfo, const QString &why)
- +{
- + QMutexLocker locker(&m_queueLock);
- + reschedQueue.enqueue(ScheduledRecording::BuildCheckRequest(recinfo,
- + why));
- +}
- +
- +void Scheduler::EnqueuePlace(const QString &why)
- +{
- + QMutexLocker locker(&m_queueLock);
- + reschedQueue.enqueue(ScheduledRecording::BuildPlaceRequest(why));
- +}
- +
- +bool Scheduler::HaveQueuedRequests(void)
- +{
- + QMutexLocker locker(&m_queueLock);
- + return !reschedQueue.empty();
- +}
- +
- +void Scheduler::ClearRequestQueue(void)
- +{
- + QMutexLocker locker(&m_queueLock);
- + reschedQueue.clear();
- +}
- +
- /* vim: set expandtab tabstop=4 shiftwidth=4: */
- diff --git a/mythtv/programs/mythbackend/scheduler.h b/mythtv/programs/mythbackend/scheduler.h
- index 2df7b68..8a92d92 100644
- --- a/mythtv/programs/mythbackend/scheduler.h
- +++ b/mythtv/programs/mythbackend/scheduler.h
- @@ -184,17 +184,16 @@ class Scheduler : public MThread, public MythScheduler
- bool &statuschanged);
- void EnqueueMatch(uint recordid, uint sourceid, uint mplexid,
- - const QDateTime maxstarttime, const QString &why)
- - { reschedQueue.enqueue(ScheduledRecording::BuildMatchRequest(recordid,
- - sourceid, mplexid, maxstarttime, why)); };
- - void EnqueueCheck(const RecordingInfo &recinfo, const QString &why)
- - { reschedQueue.enqueue(ScheduledRecording::BuildCheckRequest(recinfo,
- - why)); };
- - void EnqueuePlace(const QString &why)
- - { reschedQueue.enqueue(ScheduledRecording::BuildPlaceRequest(why)); };
- + const QDateTime maxstarttime, const QString &why);
- + void EnqueueCheck(const RecordingInfo &recinfo, const QString &why);
- + void EnqueuePlace(const QString &why);
- +
- + bool HaveQueuedRequests(void);
- + void ClearRequestQueue(void);
- MythDeque<QStringList> reschedQueue;
- mutable QMutex schedLock;
- + mutable QMutex m_queueLock;
- QMutex recordmatchLock;
- QWaitCondition reschedWait;
- RecList reclist;
advertising
Update the Post
Either update this post and resubmit it with changes, or make a new post.
You may also comment on this post.
Please note that information posted here will expire by default in one month. If you do not want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords. All illegal activities will be reported and any information will be handed over to the authorities, so be good.