Skip to content

Commit 35fd63c

Browse files
Threading Scheduler cleanups. See [a5a2a9c].
* Gets rid of the use of QThread::terminate() in scheduler shutdown (unsafe). * Makes sure the thread is running when needed using a conditional. * Makes Scheduler a QThread itself since it was already a QObject. The first change is for a problem that existed before the port, I just happened to catch it because I was doing a code review. The second change is for a problem introduced by the port (very unlikely to cause any problems in this case). The third change should not affect functionality at all.
1 parent 2e28890 commit 35fd63c

File tree

2 files changed

+39
-46
lines changed

2 files changed

+39
-46
lines changed

mythtv/programs/mythbackend/scheduler.cpp

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Scheduler::Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
5757
schedulingEnabled(true),
5858
m_tvList(tvList),
5959
expirer(NULL),
60+
doRun(runthread),
6061
m_mainServer(NULL),
6162
resetIdleTime(false),
6263
m_isShuttingDown(false),
@@ -69,7 +70,7 @@ Scheduler::Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
6970
master_sched->getAllPending(&reclist);
7071

7172
// Only the master scheduler should use SchedCon()
72-
if (runthread)
73+
if (doRun)
7374
dbConn = MSqlQuery::SchedCon();
7475
else
7576
dbConn = MSqlQuery::DDCon();
@@ -88,22 +89,30 @@ Scheduler::Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
8889

8990
fsInfoCacheFillTime = QDateTime::currentDateTime().addSecs(-1000);
9091

91-
if (runthread)
92+
if (doRun)
9293
{
93-
schedThread.SetParent(this);
94-
schedThread.start(QThread::LowPriority);
95-
96-
if (!schedThread.isRunning())
9794
{
98-
VERBOSE(VB_IMPORTANT, QString("Failed to start scheduler thread"));
95+
QMutexLocker locker(&schedLock);
96+
start(QThread::LowPriority);
97+
while (doRun && !isRunning())
98+
reschedWait.wait(&schedLock);
9999
}
100-
101100
WakeUpSlaves();
102101
}
103102
}
104103

105104
Scheduler::~Scheduler()
106105
{
106+
QMutexLocker locker(&schedLock);
107+
if (doRun)
108+
{
109+
doRun = false;
110+
reschedWait.wakeAll();
111+
locker.unlock();
112+
wait();
113+
locker.relock();
114+
}
115+
107116
while (!reclist.empty())
108117
{
109118
delete reclist.back();
@@ -115,12 +124,6 @@ Scheduler::~Scheduler()
115124
delete worklist.back();
116125
worklist.pop_back();
117126
}
118-
119-
if (schedThread.isRunning())
120-
{
121-
schedThread.terminate();
122-
schedThread.wait();
123-
}
124127
}
125128

126129
void Scheduler::SetMainServer(MainServer *ms)
@@ -1670,7 +1673,7 @@ bool Scheduler::IsBusyRecording(const RecordingInfo *rcinfo)
16701673
return false;
16711674
}
16721675

1673-
void Scheduler::RunScheduler(void)
1676+
void Scheduler::run(void)
16741677
{
16751678
// Mark anything that was recording as aborted. We'll fix it up.
16761679
// if possible, after the slaves connect and we start scheduling.
@@ -1683,6 +1686,12 @@ void Scheduler::RunScheduler(void)
16831686
if (!query.exec())
16841687
MythDB::DBError("UpdateAborted", query);
16851688

1689+
// Notify constructor that we're actually running
1690+
{
1691+
QMutexLocker lockit(&schedLock);
1692+
reschedWait.wakeAll();
1693+
}
1694+
16861695
// wait for slaves to connect
16871696
sleep(3);
16881697

@@ -1704,7 +1713,7 @@ void Scheduler::RunScheduler(void)
17041713
int maxSleep = 60000; // maximum sleep time in milliseconds
17051714
int schedRunTime = 30; // max scheduler run time in seconds
17061715

1707-
while (true)
1716+
while (doRun)
17081717
{
17091718
QDateTime curtime = QDateTime::currentDateTime();
17101719
bool statuschanged = false;
@@ -1717,13 +1726,16 @@ void Scheduler::RunScheduler(void)
17171726
{
17181727
int msecs = CalcTimeToNextHandleRecordingEvent(
17191728
curtime, startIter, reclist, prerollseconds, maxSleep);
1720-
if (msecs > 200)
1729+
while (doRun && (msecs > 200))
17211730
{
1722-
schedLock.unlock(); // allow GetRecStatus(), etc. to work
17231731
VERBOSE(VB_SCHEDULE,
17241732
QString("sleeping for %1 ms").arg(msecs));
1725-
(void) ::usleep(msecs * 1000);
1726-
schedLock.lock();
1733+
reschedWait.wait(&schedLock, msecs);
1734+
if (doRun)
1735+
{
1736+
msecs = CalcTimeToNextHandleRecordingEvent(
1737+
curtime, startIter, reclist, prerollseconds, maxSleep);
1738+
}
17271739
}
17281740
}
17291741
else
@@ -1736,6 +1748,8 @@ void Scheduler::RunScheduler(void)
17361748
QString("sleeping for %1 ms (interuptable)")
17371749
.arg(sched_sleep));
17381750
reschedWait.wait(&schedLock, sched_sleep);
1751+
if (!doRun)
1752+
break;
17391753
}
17401754

17411755
QTime t; t.start();
@@ -2861,14 +2875,6 @@ void Scheduler::WakeUpSlaves(void)
28612875
}
28622876
}
28632877

2864-
void ScheduleThread::run(void)
2865-
{
2866-
if (!m_parent)
2867-
return;
2868-
2869-
m_parent->RunScheduler();
2870-
}
2871-
28722878
void Scheduler::UpdateManuals(int recordid)
28732879
{
28742880
MSqlQuery query(dbConn);
@@ -3716,8 +3722,7 @@ void Scheduler::AddNewRecords(void)
37163722

37173723
RecStatusType newrecstatus = p->GetRecordingStatus();
37183724
// Check for rsOffLine
3719-
if ((schedThread.isRunning() || specsched) &&
3720-
!cardMap.contains(p->GetCardID()))
3725+
if ((doRun || specsched) && !cardMap.contains(p->GetCardID()))
37213726
newrecstatus = rsOffLine;
37223727

37233728
// Check for rsTooManyRecordings

mythtv/programs/mythbackend/scheduler.h

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ using namespace std;
1010
#include <QWaitCondition>
1111
#include <QObject>
1212
#include <QString>
13+
#include <QThread>
1314
#include <QMutex>
1415
#include <QMap>
15-
#include <QThread>
1616

1717
// MythTV headers
1818
#include "recordinginfo.h"
@@ -33,22 +33,10 @@ typedef RecList::iterator RecIter;
3333

3434
class Scheduler;
3535

36-
class ScheduleThread : public QThread
37-
{
38-
Q_OBJECT
39-
public:
40-
ScheduleThread() : m_parent(NULL) {}
41-
void SetParent(Scheduler *parent) { m_parent = parent; }
42-
void run(void);
43-
private:
44-
Scheduler *m_parent;
45-
};
46-
47-
class Scheduler : public QObject
36+
class Scheduler : public QThread
4837
{
4938
Q_OBJECT
5039

51-
friend class ScheduleThread;
5240
public:
5341
Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
5442
QString recordTbl = "record", Scheduler *master_sched = NULL);
@@ -97,7 +85,7 @@ class Scheduler : public QObject
9785
int GetError(void) const { return error; }
9886

9987
protected:
100-
void RunScheduler(void);
88+
virtual void run(void); // QThread
10189

10290
private:
10391
QString recordTable;
@@ -202,7 +190,7 @@ class Scheduler : public QObject
202190

203191
QMap<QString, bool> recPendingList;
204192

205-
ScheduleThread schedThread;
193+
bool doRun;
206194

207195
MainServer *m_mainServer;
208196

0 commit comments

Comments
 (0)