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:
Workeris 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
Workerconstructs aWatchdogon the heapclass Watchdog : public QThread { Q_OBJECT public: Watchdog(); void run(); public slots: void tick(); signals: void ownerIsDead(); };The constructor does
QObject::connect()between theWatchdogandWorkersignals and slotsconnect(this, SIGNAL(tick()), watchdog, SLOT(tick())); connect(watchdog, SIGNAL(ownerIsDead()), this, SLOT(ownerDied()));The main loop of the
Workerstarts in theWorker::run()method.The
Workerstarts theWatchdog. TheWatchdogloop is started.If the
Workerdoes nottick()within 5 seconds of thestart()call, theWatchdogemits theownerIsDead()signal- Worker processes the
ownerDied()signal, killing the mainWorkerloop - If the
Workerdoes 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.
