I've created WorkerThread
class extended QThread
as follow:
// https://stackoverflow.com/a/14546167/11073131
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#include <QDebug>
#include <QString>
#include "ud_ucase.h"
class WorkerThread : public QThread {
Q_OBJECT
public:
void run() {
struct sockaddr_un svaddr, claddr;
int sfd, j;
ssize_t numBytes;
socklen_t len;
char buf[BUF_SIZE];
sfd = socket(AF_UNIX, SOCK_DGRAM, 0); // Create server socket
if (sfd == -1)
qDebug() << "socket";
// Construct well-known address and bind server socket to it
if (strlen(SV_SOCK_PATH) > sizeof(svaddr.sun_path) - 1)
printf("Server socket path too long: %s", SV_SOCK_PATH);
if (remove(SV_SOCK_PATH) == -1 && errno != ENOENT)
printf("remove-%s", SV_SOCK_PATH);
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_un)) == -1)
printf("bind");
// Receive messages, convert to uppercase, and return to client
while(1) {
len = sizeof(struct sockaddr_un);
qDebug() << "before recvfrom";
emit progressChanged("before recvfrom"); // 1st emit
numBytes = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &claddr, &len);
if (numBytes == -1)
printf("recvfrom");
printf("Server received %ld bytes from %s\n", (long) numBytes,
claddr.sun_path);
buf[numBytes] = 0;
qDebug() << "buf:" << buf;
emit progressChanged(buf); // 2nd emit
qDebug() << "Emit finished";
// Convert received messages to uppercase
for (j = 0; j < numBytes; j++)
buf[j] = toupper((unsigned char) buf[j]);
// Return back it to client socket
if (sendto(sfd, buf, numBytes, 0, (struct sockaddr *) &claddr, len) !=
numBytes)
printf("sendto");
}
/*
while(1) {
// ... hard work
// Now want to notify main thread:
emit progressChanged("Some info");
}
*/
}
// Define signal:
signals:
void progressChanged(QString info);
};
#endif // THREAD_H
The run()
method of the above class creates & runs a UnixDomain datagram socket server
that emits the received string by a signal progressChanged(QString info)
, converts this string to uppercase, then returns to the client socket.
The slot that receives the signal mentioned above is defined on the mainwindow.cpp
as follow:
void MainWindow::onProgressChanged(QString info) {
// Processing code
ui->label->setText("Latest info: " + info);
qDebug() << "Signal received:" << info;
}
void MainWindow::startWorkInAThread() {
// Create an instance of your woker
WorkerThread *workerThread = new WorkerThread;
// Connect our signal and slot
connect(workerThread, SIGNAL(progressChanged(QString)),
SLOT(onProgressChanged(QString)));
// Setup callback for cleanup when it finishes
connect(workerThread, SIGNAL(finished()),
workerThread, SLOT(deleteLater()));
// Run, Forest, run!
workerThread->start(); // This invokes WorkerThread::run in a new thread
}
The function MainWindow::startWorkInAThread()
connecting the signal and the slot is called in the constructor of MainWindow.
When runs this application, the 1st emit
is received by MainWindow::onProgressChanged(QString info)
with following QDebug message:
before recvfrom
Signal received: "before recvfrom"
Then, send message "aho" from external socket client, the QDebug message indicates that the 2nd emit, which emit the signal with received message by recvfrom() function of the socket, was emitted, but never received. Also next 1st emit also was emitted but never received.
before recvfrom
Signal received: "before recvfrom"
buf: aho
Emit finished
before recvfrom
And the socket client receive uppercase converted message as expected.
./ud_ucase_cl aho
Response 1: AHO
Considering that
Why after recvfrom() on the Qthread class any message get never received? How Can I fix this?
Qt 5.11.3 Raspberry Pi 2B+ Linux raspberrypi 5.10.103-v7+ #1529 SMP Tue Mar 8 12:21:37 GMT 2022 armv7l GNU/Linux GCC 8.3.0
I've succeeded in making a minimum reproducing environment as datagramRep, and I've found the most suspicious stuff is the QTimer object in mainwindow.cpp because the issue doesn't reproduce when I don't call timer->start(1000)
or increases interval to 60000. The above threshold might be device-dependent. I've confirmed this with my RPi 2 Model B.
It seems weird why a 1-second interval QTimer blocks to receive Signal. But it might be so.