QSocketNotifier: Can only be used with threads started with QThread error - c++

I'm trying to use QLocalServer as an ipc solution. The version of qt is 4.6
This is my main.cpp:
int main(int argc, const char*argv[]) {
QServer test();
while (true) {
}
}
This is my QServer class:
class QServer : public QObject
{
Q_OBJECT
public :
QServer ();
virtual ~QServer();
private :
QLocalServer* m_server;
QLocalSocket* m_connection;
private slots:
void socket_new_connection();
};
QServer::QServer()
{
m_server = new QLocalServer(this);
if (!m_server->listen("DLSERVER")) {
qDebug() << "Testing";
qDebug() << "Not able to start the server";
qDebug() << m_server->errorString();
qDebug() << "Server is " << m_server->isListening();
}
connect(m_server, SIGNAL(newConnection()),
this, SLOT(socket_new_connection()));
}
void
QServer::socket_new_connection()
{
m_connection = m_server->nextPendingConnection();
connect(clientConnection, SIGNAL(readyRead()),
this, SLOT(newData(clientConnection)));
}
This all compiles, however at runtime, when I try to connect newConnection(), I get a QSocketNotifier: Can only be used with threads started with QThread error.
I have tried wrapping this whole thing in a QThread, but I still got the same error.
Can anybody explain what I'm doing wrong or why there's even a thread involved?

The error message is misleading. You need a Qt event loop in order to use QSocketNotifier. The appropriate way to do that in your application is to create a QApplication (or if you don't want any graphical stuff, a QCoreApplication). Your main should look like:
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
QServer test();
app.exec();
return 0;
}
QCoreApplication::exec() starts the event loop (which replaces your while (true) {} loop).

Related

QT Serialport GUI and worker thread

First things first, I'm a newbie in QT so don't blame me. I know that many similar questions have been in the forum, but I couldn't solve my problem.
Problem description. I want to have a GUI application that receives and parses data and update some qt widget. Formerly I did them all in the Mainwindow thread, but since it hangs, I tried to make it multi-threaded. But it still hangs when I try to update GUI data as fast as 10 ms.
Now, this is what I have tried.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
class Parser : public QThread , public QRunnable
{
Q_OBJECT
public:
explicit Parser(QThread *parent = nullptr);
~Parser();
signals:
void data1Available(unsigned char*);
void data2Available(unsigned char*);
void finished();
// QRunnable interface
public:
void run();
public slots:
void parse();
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect( &SerialPort, SIGNAL(readyRead()), this, SLOT(ReadData()) );
QThread* thread = new QThread;
thread->setObjectName("Parser Thread");
qInfo()<<"Parser Thread";
Parser* parser= new Parser();
parser->moveToThread(thread);
QObject::connect(thread,&QThread::started,parser,&Parser::run);
QObject::connect(parser,&Parser::finished,parser,&Parser::deleteLater);
QObject::connect(parser,&Parser::finished,thread,&QThread::quit);
QObject::connect(thread,&QThread::finished,thread,&QThread::deleteLater);
QObject::connect(parser,SIGNAL(data1Available(unsigned char *)),this,SLOT(on_data1Available(unsigned char *)));
QObject::connect(parser,SIGNAL(data2Available(unsigned char *)),this,SLOT(on_data2Available(unsigned char *)));
thread->start();
}
void MainWindow::ReadData()
{
QByteArray Data = SerialPort.readAll();
for (unsigned char i=0;i<Data.length();i++)
circBuff.append(Data[i]);
}
void MainWindow::on_data1Available(unsigned char* tempData)
{
ui->label1->setNum(tempData[5]);
}
void MainWindow::on_data2Available(unsigned char* tempData)
{
ui->label2->setNum(tempData[7]);
}
void Parser::run()
{
qInfo()<<this<<Q_FUNC_INFO<<QThread::currentThread();
QScopedPointer<QEventLoop> loop (new QEventLoop);
QScopedPointer<QTimer> timer (new QTimer);
timer->setInterval(5);
connect(timer.data(),&QTimer::timeout,this,&Parser::parse);
connect(this,&Parser::finished,loop.data(),&QEventLoop::quit);
timer->start();
loop->exec();
qInfo()<<this<<"Finished... "<<QThread::currentThread();
}
void Parser::parse()
{
unsigned char tempData[16];
while (1)
{
while (circBuff.size()>=16)
{
if ( )
{
if ()
emit data1Available(tempData);
else
emit data2Available(tempData);
}
}
}
emit finished();
}

Qt Signal/Slot Issue

I can't figure out what's going wrong here.
I want to pass a value from a class to another.
Here's the code:
mainwindow.h
public slots:
void printNumbers(int);
mainwindow.cpp
void MainWindow::printNumbers(int a)
{
qDebug() << a;
}
myudp.h
signals:
inline void sendBuff(int);
myudp.cpp
[***]
MainWindow *widget = new MainWindow();
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
const bool connected = connect(this , SIGNAL(sendBuff(int)), widget ,SLOT(printNumbers(int)));
qDebug() << "Connection established?" << connected;
[***]
void MyUDP::readyRead()
{
// when data comes in
emit sendBuff(13);
[***]
}
inline void MyUDP::sendBuff(int a)
{
qDebug() << "sending " << a ;
}
Main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow window;
MainWindow *widget = new MainWindow();
window.setCentralWidget(widget);
window.resize(900, 600);
window.show();
MyUDP *client = new MyUDP();
return a.exec();
}
I used "inline" because of an error: duplicate MyUDP::sendBuff(int a).
I don't know if it can be an issue.
when I execute the "emit sendBuff(12)" I only receive "sending 12", I didn't catch the printNumbers()'s output even if the variable "connected" is true.
remove the inline declaration of the slot, and if your class needs an internal use for sendBuff then declare a new method for that...
signals:
void sendBuffSignal(int);
and in the cpp
void MyUDP::sendBuff(int a)
{
qDebug() << "sending " << a ;
}

how to use QProcess to wrap telenet.exe on Windows?

I'm trying to code a wrapper class using QProcess to drive the CLI applications (e.g. telnet.exe, ftp.exe) on Windows but so far with no luck. Do you know if this is even possible?
Below is the code I used to try with telnet.exe on Windows 7. I was expecting this code will print out the "welcome message" after telnet connected to the server but there is nothing print out (from standard output or error output).
#include <QCoreApplication>
#include <QProcess>
#include <iostream>
class ProcessWrapper :public QObject
{
Q_OBJECT
public:
ProcessWrapper();
~ProcessWrapper();
void start();
public slots:
void readStandardError();
void readStandardOutput();
private:
QProcess *process;
};
ProcessWrapper::ProcessWrapper()
{
process = new QProcess(this);
connect(process, SIGNAL(readyReadStandardError()), this, SLOT(readStandardError()));
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));
}
void ProcessWrapper::start()
{
if(process) {
process->start("telnet.exe",QStringList() << "135.251.142.36");
process->waitForStarted();
}
}
ProcessWrapper::~ProcessWrapper()
{
if(process) delete process;
}
void ProcessWrapper::readStandardOutput()
{
if(process) {
QByteArray s = process->readAllStandardOutput();
QString str(s);
std::cout << str.toStdString();
}
}
void ProcessWrapper::readStandardError()
{
if(process) {
QByteArray s = process->readAllStandardError();
QString str(s);
std::cout << str.toStdString();
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ProcessWrapper p;
p.start();
return a.exec();
}
#include "main.moc"
The function main() exit immediately after you called ProcessWrapper::start().

Qt 5 and QProcess redirect stdout with signal/slot readyRead

This problem is bothering me because it should work, but sadly it does not.
What i try to achieve is to read the standard output of a certain process and make another process handle it i.e. print it out.
The process that produces output looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int main() {
for (int i = 0; i < 100; i++) {
printf("yes %d\n",i);
fflush(stdout);
sleep(1);
}
return 0;
}
The process is started in another application like this:
#include <QProcess>
...
QProcess * process = new QProcess;
SomeClass * someClass = new SomeClass(process);
connect(process,SIGNAL(readyRead()),someClass,SLOT(onReadyRead()));
process->start("../Test/Test",QStringList());
if (!process->waitForStarted(4000)) {
qDebug() << "Process did not start.";
}
...
void SomeClass::onReadyRead() {
qDebug() << "Reading:" << process->readAllStdOutput();
}
My expected output would be:
Reading: yes 0
Reading: yes 1
...
Reading: yes 99
However i get no output at all.
And when i use QCoreApplication i get all the output but not through the signal/slot but directly in the console.
I dont understand because it works in another application that uses Qt 4.8.
My question is, is anyone experiencing the same problem or does anyone know how i can get the expected behaviour?
Your problem in the answer you provide lies in misunderstanding how the reading works. It simply returns whatever data you've got there, whether there are line endings or not. By spawning a thread and sleeping between lines, you're effectively sending the inter-process data in line-sized chunks since the pipe is flushed when you wait long enough.
So, your answer, while working, is not really how one should do it. You need to use readLine() to chop the incoming data into lines. Below is an example with following qualities:
There's just one executable :)
Only Qt apis are used. This reduces the runtime memory consumption.
Both processes cleanly terminate.
The amount of code is as minimal as practicable.
// https://github.com/KubaO/stackoverflown/tree/master/questions/process-17856897
#include <QtCore>
QTextStream out{stdout};
class Slave : public QObject {
QBasicTimer m_timer;
int m_iter = 0;
void timerEvent(QTimerEvent * ev) override {
if (ev->timerId() == m_timer.timerId()) {
out << "iteration " << m_iter++ << endl;
if (m_iter > 35) qApp->quit();
}
}
public:
Slave(QObject *parent = nullptr) : QObject(parent) {
m_timer.start(100, this);
}
};
class Master : public QObject {
Q_OBJECT
QProcess m_proc{this};
Q_SLOT void read() {
while (m_proc.canReadLine()) {
out << "read: " << m_proc.readLine();
out.flush(); // endl implicitly flushes, so we must do the same
}
}
Q_SLOT void started() {
out << "started" << endl;
}
Q_SLOT void finished() {
out << "finished" << endl;
qApp->quit();
}
public:
Master(QObject *parent = nullptr) : QObject(parent) {
connect(&m_proc, SIGNAL(readyRead()), SLOT(read()));
connect(&m_proc, SIGNAL(started()), SLOT(started()));
connect(&m_proc, SIGNAL(finished(int)), SLOT(finished()));
m_proc.start(qApp->applicationFilePath(), {"dummy"});
}
};
int main(int argc, char *argv[])
{
QCoreApplication app{argc, argv};
if (app.arguments().length() > 1)
new Slave{&app}; // called with an argument, this is the slave process
else
new Master{&app}; // no arguments, this is the master
return app.exec();
}
#include "main.moc"
Based on the code you've posted, you're connecting to the class slot with this: -
connect(process,SIGNAL(readyRead()),someClass,SLOT(onReadyReadStdOutput()));
But the function in the class is declared like this: -
void SomeClass::onReadyRead();
If you're expecting onReadyRead to be called, then you should be calling it in the SLOT, rather than onReadyReadStdOutput. So change your connection to: -
connect(process,SIGNAL(readyRead()),someClass,SLOT(onReadyRead()));
Well i solved my problem.
If the process is started with startDetached() it will not receive the signals from readyRead(), readyReadStandardOutput() and readyReadStandardError().
So just starting it with start() solved the problem.
However i noticed that if i start and do the while loop and prints in main() it will read everything at once even if it ends with \n. So i started the while loop in a thread and that problem was also solved. Everything prints as expected.
#include <QThread>
class Thread : public QThread
{
Q_OBJECT
public:
explicit Thread(QObject *parent = 0) : QThread(parent) {}
protected:
void run() {
for (int i = 0; i < 100; i++) {
std::cout << "yes" << i << std::endl;
msleep(200);
}
exit(0);
}
};
int main(int argc, char ** argv) {
QCoreApplication app(argc,argv);
Thread * t = new Thread();
t->start();
return app.exec();
}
TestP main.cpp
#include <QProcess>
#include <iostream>
class Controller : public QObject
{
Q_OBJECT
private:
QProcess * process;
public:
Controller(QObject *parent = 0) :
QObject(parent), process(new QProcess) {}
void init(const QString &program) {
connect(process,SIGNAL(readyRead()),this,SLOT(readStdOut()));
connect(process,SIGNAL(started()),this,SLOT(onStarted()));
connect(process,SIGNAL(finished(int)),this,SLOT(onFinished(int)));
process->start(program);
}
private slots:
void readStdOut() {
std::cout << "YES " << QString(process->readAllStandardOutput()).toUtf8().constData() << std::endl;
}
void onStarted(){
std::cout << "Process started" << std::endl;
}
void onFinished(int) {
std::cout << "Process finished: " << signal << std::endl;
}
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
Controller c;
c.init("../Test/Test");
return a.exec();
}

GTK::main::run segfaults

I'm trying to write a GTK program. I managed to get my window to spawn with a button in it, but now when I try to pack a box and add 2 buttons to the box I segfault. What confuses me is that it doesn't segfault when I create anything, but insead when i run GTK::Main::run.
int main(int argc, char *argv[])
{
Glib::RefPtr<Gtk::Application> app =
Gtk::Application::create(argc, argv,
"org.gtkmm.examples.base");
MainWindow mainWindow;
cout << "trying to run window"<< endl;
Gtk::Main::run(mainWindow);
cout << "done running window"<< endl;
return 0;
}
and
MainWindow::MainWindow()
:quit_button("Quit"),
write_button("Write"),
window_box()
{
set_border_width(10);
quit_button.signal_clicked().connect(sigc::mem_fun(*this,
&MainWindow::quit_button_clicked));
write_button.signal_clicked().connect(sigc::mem_fun(*this,
&MainWindow::write_button_clicked));
window_box.start_pack(quit_button);
window_box.start_pack(write_button);
add(window_box);
write_button.show();
quit_button.show();
window_box.show();
}
MainWindow::~MainWindow()
{
}
void MainWindow::write_button_clicked()
{
std::cout << "Hello World" << std::endl;
}
void MainWindow::quit_button_clicked()
{
exit(0);
}
are my main method and my constructor for my MainWindow class. I've tried not packing anything or packing less things and I still segfault. I'm brand new to GTK so I know I must be missing something simple.
Edit: Main Window Declaration
#include <gtkmm.h>
#include <iostream>
using namespace std;
class MainWindow : public Gtk::Window
{
public:
MainWindow();
~MainWindow();
protected:
//Signal Handlers
void write_button_clicked();
void quit_button_clicked();
//Widgets
Gtk::Button quit_button;
Gtk::Button write_button;
Gtk::VBox window_box;asd
};
#endif // GTKMM_EXAMPLE_HELLOWORLD_H
Gtk::Main has been deprecated and replaced by Gtk::Application, it handles the event loop now.
It works if instead of Gtk::Main::run(mainWindow); you use app->run(mainWindow);
like ergosys said.
For proper cleanup, you should probably call app->quit() instead of libc's quit(), too (or just close the window, which will terminate the main loop too)