I have the current situation:
The Worker is a field in the MainWindow class, the Watchdog is a field in the Worker class.
The execution goes like this:
Worker
is constructedclass Worker : public QThread { Q_OBJECT public: explicit Worker(); void run(); private: Watchdog *watchdog; bool running = false; signals: void tick(); public slots: void ownerDied(); };
The constructor of
Worker
constructs aWatchdog
on the heapclass Watchdog : public QThread { Q_OBJECT public: Watchdog(); void run(); public slots: void tick(); signals: void ownerIsDead(); };
The constructor does
QObject::connect()
between theWatchdog
andWorker
signals and slotsconnect(this, SIGNAL(tick()), watchdog, SLOT(tick())); connect(watchdog, SIGNAL(ownerIsDead()), this, SLOT(ownerDied()));
The main loop of the
Worker
starts in theWorker::run()
method.The
Worker
starts theWatchdog
. TheWatchdog
loop is started.If the
Worker
does nottick()
within 5 seconds of thestart()
call, theWatchdog
emits theownerIsDead()
signal- Worker processes the
ownerDied()
signal, killing the mainWorker
loop - If the
Worker
does tick theWatchdog
, he sleeps another 5 seconds - The whole process repeats
The problem is, the tick()
never reaches the Watchdog
, nor does the ownerIsDead()
signal reach the worker because it did not tick. Why?
Here is the raw code, the class names are a bit different.
watchdog.h
#ifndef WATCHDOG_H
#define WATCHDOG_H
#define THRESHOLD 1000
#include <QThread>
#include <QObject>
class Watchdog : public QThread
{
Q_OBJECT
public:
Watchdog();
void run();
public slots:
void tick();
void kill();
private:
bool running = false;
bool ticked = false;
signals:
void error();
};
#endif // WATCHDOG_H
watchdog.cpp
#include "watchdog.h"
#include <QDebug>
Watchdog::Watchdog()
{
}
void Watchdog::run()
{
running = true;
qDebug() << "Starting watchdog";
while (running) {
QThread::msleep(THRESHOLD);
qDebug() << "Watchdog tick ... ";
if (!ticked) {
qDebug() << "read() or write() is read";
emit error();
}
}
}
void Watchdog::tick()
{
qDebug() << "Watchdog ticking";
ticked = true;
}
void Watchdog::kill()
{
qDebug() << "Killing watchdog...";
running = false;
}
diskerror.h ( AKA the 'Worker' )
#ifndef DISKERROR_H
#define DISKERROR_H
#include <QThread>
#include <watchdog.h>
extern "C" {
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <malloc.h>
}
class DiskError : public QThread
{
Q_OBJECT
public:
explicit DiskError();
void run();
private:
int mismatch(char *a, char *b);
Watchdog *watchdog;
bool running = false;
signals:
void tick();
void killWatchdog();
public slots:
void ownerIsDead();
};
#endif // DISKERROR_H
diskerror.cpp
include "diskerror.h"
#include "watchdog.h"
#include <QDebug>
#define BLKSZ 4096
DiskError::DiskError()
{
watchdog = new Watchdog();
connect(this, SIGNAL(killWatchdog()), watchdog, SLOT(kill()));
connect(this, SIGNAL(tick()), watchdog, SLOT(tick()));
connect(watchdog, SIGNAL(error()), this, SLOT(ownerIsDead()));
}
void DiskError::run()
{
int fd = open("/dev/sdc", O_RDWR | O_SYNC);
if (fd < 0) {
qDebug() << strerror(errno);
}
size_t size;
if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
qDebug() << "IOCTL Error";
return;
}
size_t step = (size / 2500);
size_t done = 0;
int i = 0;
char testing[BLKSZ];
char pattern[BLKSZ];
for (int i = 0; i < BLKSZ; i++) {
pattern[i] = 0xCF;
}
int re, bb, wr;
off_t curr = 0;
watchdog->start();
running = true;
while (running) {
lseek(fd, curr, SEEK_SET);
wr = write(fd, pattern, BLKSZ); /* Write pattern to disk */
lseek(fd, curr, SEEK_SET);
re = read(fd, testing, BLKSZ); /* Read pattern back from disk */
bb = mismatch(pattern, testing);
curr += BLKSZ;
done += BLKSZ;
emit tick();
if ( (re == 0) || (wr < 0) ) {
qDebug() << "Flushing buffers...";
sync();
break;
}
if (done >= step) {
if (bb) {
qDebug() << "[" << i << "] Error occured";
} else {
qDebug() << "[" << i << "] OK";
}
done = 0;
i++;
}
}
emit killWatchdog();
sync();
if (close(fd) < 0) {
qDebug() << "Error closing device";
}
}
int DiskError::mismatch(char *a, char *b)
{
for (int i = 0; i < BLKSZ; i++) {
if ( (*(a+i)) != (*(b+i)) ) return 1;
}
return 0;
}
void DiskError::ownerIsDead()
{
qDebug() << "read() call blocked for more than 5 seconds, device inoperable";
}
I never see the debug text in the worker class, nor do I see the tick text in the worker.