QTcpSocket pointer produces SIGSEGV in a view. (QT5) - c++

Hi,
I've got a SIGSEGV when I want to use a QTcpSocket with the following code. (more explanation at the very bottom)
Function to create a QTTCPSocket (which will keep the QTcpSocket pointer):
std::shared_ptr<QTTCPSocket> createQtSocket(std::string host, unsigned int port)
{
QTcpSocket *sock = new QTcpSocket;
sock->connectToHost(QHostAddress(QString::fromStdString(host)), port);
if (!sock->waitForConnected())
throw std::runtime_error("Connection refused");
return std::make_shared<QTTCPSocket>(sock);
}
QTTCPSocket class:
class QTTCPSocket {
public:
QTTCPSocket(QTcpSocket *socket)
: _socket(socket)
{};
~QTTCPSocket() = default;
void send(const std::string &msg)
{
std::cout << msg << std::endl;
_socket->write(&msg[0], static_cast<qint64>(msg.length())); // produces a SIGSEGV if called from a qt event (a button for example)
_socket->waitForBytesWritten(0);
}
private:
QTcpSocket *_socket;
};
Main function:
int main()
{
std::shared_ptr<QTTCPSocket> socket = createQtSocket("127.0.0.1", 33333);
ViewStateMachine vsm(socket);
vsm.init();
vsm.start();
}
ViewStateMachine class (hpp):
class ViewStateMachine {
public:
ViewStateMachine(std::shared_ptr<QTTCPSocket> sock);
void init();
void start();
std::shared_ptr<QTTCPSocket> getSock();
private:
LoginView *_loginView;
std::shared_ptr<QTTCPSocket> _sock;
};
ViewStateMachine class (cpp):
#include "ViewStateMachine.hpp"
ViewStateMachine::ViewStateMachine(std::shared_ptr<QTTCPSocket> socket)
: _sock(std::move(socket))
{
}
void ViewStateMachine::init()
{
_loginView = new LoginView(this);
_loginView->init();
}
void ViewStateMachine::start()
{
_loginView->show();
}
std::shared_ptr<QTTCPSocket> ViewStateMachine::getSock()
{
_sock->send("test1"); // SIGSEGV inside (check above)
return _sock; // if I remove _sock->send("test1"), it SIGSEGV in the shared_ptr's constructor (only if called from a qt event (a button for example)
}
LoginView is a passive class, which register an event with QObject::connect(_connectBtn, SIGNAL(clicked()), this, SLOT(onClick_connectBtn())); with onClick_connectBtn() a member function of LoginView.
All these pieces of code might be confused so here a step-by-step explanation:
Start in main(): create a QTcpSocket * contained in a QTTCPSocket class contained in a std::shared_ptr<QTTCPSocket>.
Create a ViewStateMachine instance with the shared_ptr, which will be stored in the instance. We will call it vsm.
Call vsm.init() which will create a LoginView instance with this (vsm). LoginView will store the ViewStateMachine instance.
Call vsm.start() which will call _loginView.show() (from QT's QWidget), it will show the login view.
Everything works well and we can see the login view.
However, if I want to use my socket in the LoginView :
* when I want to use it from _loginView->init() or in the LoginView's constructor, it works well!
* when I want to use it from LoginView::onClick_connectBtn (called by QT, perhaps in a special environment like a constructor, not sure), it produces a SIGSEGV where I commented above in the code (shared_ptr's constructor or write function from the QT' socket).
To get the socket from LoginView, I use ViewStateMachine::getSock() (_viewStateMachine->getSock()).
Valgrind shows
pure virtual method called
terminate called without an active exception
The shared_ptr's constructor produces a SIGSEGV when it uses its mutex to increment the value.
The write SIGSEGV when I use _socket (QT' socket). The pointer address didn't change from beginning to end.
If there's any other question, please ask!
Thanks a lot for helping :).
EDIT: It works if I replace every std::shared_ptr with a C pointer.

Related

Qt6 Connect Signal to Lambda Function

I'm using a DataRouter class to handle communication with a QSerialPort (and then communicate the results elsewhere). The connected device sends a status package every second or so, and I would like to read it without polling the device. I tried directly using QSerialPort's waitForReadyRead function, but no matter how long I set the wait time, it always timed out. Looking here and here I saw signals can be connected to Lambda functions. Now I'm trying to connect QSerialPort's readyRead signal to a Lambda which calls my on_dataRecieved function but I get the error C2665:"QObject::connect: none of the 3 overloads could convert all of the argument types. Below is an example of what I have:
DataRouter.h
template<class SerialPort>
class DataRouter
{
public:
DataRouter ();
private slots:
on_dataRecieved();
private:
shared_ptr<SerialPort> m_port;
};
DataRouter.cpp
template<class SerialPort>
DataRouter<SerialPort>::DataRouter()
{
m_port = std::make_shared<SerialPort>()
QObject::connect(m_port, &QSerialPort::readyRead, this, [=](){this->on_dataRecieved();})
}
template<class SerialPort>
void DataRouter<SerialPort>::on_dataRecieved()
{
//Do stuff
}
If your "target" is not QObject you need to use the following overload of connect. The problem is that, you are trying to use non-QObject as "context" to determine the lifetime of the connection and that's not possible. To mitigate it you will need to release the connection somehow on DataRouter's destruction; one way is to store what connect() will have returned and call disconnect on it later on.
As for the signal coming from a smart pointer, have you tried this:
connect(m_port->get(), &QSerialPort::readyRead, &DataRouter::on_dataRecieved);
Your m_port is not entity of QSerialPort class, that's why you don't have QSerialPort::readyRead that can be emitted from it. template<class SerialPort> doesn't do what you what, it is just name of templated parameter.
You probably wanted something like this:
DataRouter.h
class DataRouter : QObject
{
public:
DataRouter ();
private slots:
on_dataRecieved();
private:
QSerialPort* m_port;
};
DataRouter.cpp
DataRouter::DataRouter()
{
m_port = new QSerialPort(this);
connect(m_port, &QSerialPort::readyRead, this, &DataRouter::on_dataRecieved);
// or connect(m_port, &QSerialPort::readyRead, this, [this](){this->on_dataRecieved();});
}
void DataRouter::on_dataRecieved()
{
//Do stuff
}
You don't have to wrap Qt classes in smart pointers as long, as you provide parent class for them. Memory freed when parent is destructed.

Call Qt object method from another std::thread

I have simple Qt form which represents main window of my app. It has method:
void gui_popup::on_pushButton_clicked()
{
QString text = ui->MainText->toPlainText();
text = "1\n" + text;
ui->MainText->setText(text);
}
Also I have some code, running in another thread, created like this:
std:thread* core_thread = new thread(&Init); //void Init()...
Then, at some moment or condition code from std::thread need to call gui_popup::on_pushButton_clicked(). I'm trying to do it like this:
void test_callback(void* object_ptr)
{
auto this_object = (gui_popup*)object_ptr;
this_object->on_pushButton_clicked();
}
In std::thread code I'm saving test_callback pointer and gui_popup object pointer. But when it starts calling on_pushButton_clicked() program halts with segmentation fault error. This code works fine with some other simple classes, but not with QtObject. What am I doing wrong?
UPDATE:
I've solved it this way:
void test_callback(void* object_ptr)
{
QMetaObject qtmo;
qtmo.invokeMethod((gui_popup*)object_ptr, "on_pushButton_clicked");
}
it is, of course, much more complex than using QThread, emitting signals and all other suggested solutions. However thank you everyone for trying to help.
I usually solve it like this:
class Foo : public QObject
{
Q_OBJECT
Foo()
{
// connect to own signal to own slot and hence "translate" it
connect(this, SIGNAL(some_signal(QString)),
this, SLOT(some_slot(QString)));
}
signals:
void some_signal(QString s);
protected slots:
void some_slot(QString s)
{
// do something with your gui
}
public:
void callback_proxy(std::string s)
{
emit some_signal(QString::fromUtf8(m_string.c_str()));
}
};
and then the tread does not need to know about QT:
void thread_run_function(Foo* foo)
{
foo->callback_proxy("Hello from Thread!");
}
As far as I understood this is save because the connect (signal,slot) does have a additional default parameter (Qt::ConnectionType type which defaults to Qt::AutoConnection). This tells QT to dispach signals into the qt main event loop if they originate from a foreign thread. Note that using this connection type essentialy makes qt decide on runtime whether to dispatch the signal or call the slot immediately.
HtH Martin
Edits: Some more info on default parameter and this link as reference:
See http://doc.qt.io/qt-5/qt.html#ConnectionType-enum

Maintaining signal connections over instance swap Qt5

In my Qt5 program I have an interface with some signals.
An implementation of this interface is instanciated at start up and the signals are connected to from different parts of the program (many places).
Now I want to delete that instance and create a new instance, possibly from another implementation, and somehow maintain the signal connections so that all the places that receive the signals does not need to care that the implementation changed.
Is there any way to do this elegantly or do I have to change the architecture of program to keep control over all signal connections in one location (a lot of work)?
Example:
//PS: To be regarded as pseudocode at best, as lots of Qt boilerplate
// and error handling code has been left out, and lots of bugs are left in :-)
struct MyInterface{
virtual void doStuff()=0;
signals:
void someSignal();
}
struct MyImpX:public MyInterface{
void doStuff(){
qDebug()<<"MyImpX";
if((random()%100)<5){
emit someSignal();
}
}
}
struct MyImpY:public MyInterface{
void doStuff(){
qDebug()<<"MyImpY";
if((random()%100)<10){
emit someSignal();
}
}
}
struct MyWorker{
QTimer t;
MyInterface *inst=0;
MyWorker(MyInterface *inst):
inst(inst)
{
connect(&t,SIGNAL(timeout()),this,SLOT(doStuff()));
t.start(100);
}
void setNewInstance(MyInterface *inst){
this->inst=inst;
}
void doStuff(){
if(0!=inst){
inst->doStuff();
}
}
}
struct MyConsumer{
public slots:
void handleIt(){
qDebug()<<"Handling signal";
}
}
void main(){
QApplication app;
MyInterface *inst=new MyImpX();
MyWorker con(inst);
MyConsumer i,j,k,l;
//In this example all the connects are in one place, but
//in reality they are called from several locations that
//Are hard to control.
connect(inst,SIGNAL(someSignal()),&i,SLOT(handleIt()));
connect(inst,SIGNAL(someSignal()),&j,SLOT(handleIt()));
connect(inst,SIGNAL(someSignal()),&k,SLOT(handleIt()));
connect(inst,SIGNAL(someSignal()),&l,SLOT(handleIt()));
//[ ... At this point some time passes where the signal is working ]
//Now the instance changes, so the old connections are lost.
con.setNewInstance(new MyImpY());
delete inst;
inst=0;
//[ ... At this point some time passes where the signal is NOT working ]
app.exec();
}
You could try to implement something based on this question, but I think that'll be hacky at best.
So, instead, you could have a proxy object, which does not get changed, and which can change its connections when the actual object changes. For this, you should probably use signal-signal connections, though you could also write slots which emit signals. Question has pseudocode, so here's some pseudocode as well, to demonstrate the principle.
class MyInterfaceSignalProxy : public MyInterface {
//...
public:
void reconnect(MyInterface *newObj, MyInterface *oldObj=0) {
if(oldObj) disconnect(oldObj, 0, this, 0); // disconnect old connections
connect(newObj, SIGNAL(someSignal()), this, SIGNAL(someSignal()));
}
signals:
void someSignal();
}
Of course you could remove the oldObj parameter, and for example store the currently connected object as private variable, or just not care about disconnection earlier connectios (for example if oldObj will be deleted or otherwise disconnected elsewhere).
And then your main would start something like:
void main(){
QApplication app;
MyInterfaceSignalProxy proxy;
MyConsumer i,j,k,l;
connect(&proxy,SIGNAL(someSignal()),&i,SLOT(handleIt()));
connect(&proxy,SIGNAL(someSignal()),&j,SLOT(handleIt()));
connect(&proxy,SIGNAL(someSignal()),&k,SLOT(handleIt()));
connect(&proxy,SIGNAL(someSignal()),&l,SLOT(handleIt()));
MyInterface *inst=new MyImpX();
proxy.reconnect(inst);
//....
MyInterface *inst2=new MyImpY();
proxy.reconnect(inst2, inst);
delete inst; // whatever

When subclassing QTcpServer, how can I delay emitting the newConnection() signal?

I want to create an SSL server, so I subclass QTcpServer and I override incomingConnection(), where I create a QSslSocket, set its descriptor, and call QSslSocket::startServerEncryption. At this point I need to wait for QSslSocket::encrypted() signal to be emitted, and only after that should my server emit the newConnection() signal. The client code would then think it's using a QTcpSocket, but will in fact be using a secure socket.
But QTcpServer always emits newConnection() after calling incomingConnection() (I looked in the source of QTcpServer):
void QTcpServerPrivate::readNotification()
{
// .........
q->incomingConnection(descriptor);
QPointer<QTcpServer> that = q;
emit q->newConnection();
// .........
}
So my question is, is there a way I can prevent QTcpServer from emitting newConnection(), until I'm ready to emit it myself?
The reason I want this is that I want my class to be able to be used as a drop-in replacement of QTcpServer, by code that is unaware it's using it, so it must behave exactly as a QTcpServer:
QTcpServer* getServer(bool ssl)
{
return ssl ? new SslServer : new QTcpServer;
}
My code for the SslServer class is currently this:
void SslServer::ready()
{
QSslSocket *socket = (QSslSocket *) sender();
addPendingConnection(socket);
emit newConnection();
}
void SslServer::incomingConnection(int socketDescriptor)
{
QSslSocket *serverSocket = new QSslSocket;
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
connect(serverSocket, SIGNAL(encrypted()), this, SLOT(ready()));
serverSocket->startServerEncryption();
} else {
delete serverSocket;
}
}
Here's an idea that could work in this case: redefine the newConnection signal in your QTcpServer subclass.
If you do that, objects that connected with an instance of your server won't receive QTcpServer's "version" of the signal, only the one you emit directly from your sub-class.
Here's a proof of concept: class A is the QTcpServer, foo is the signal you're trying to "hijack", bar is just another (hypothetical) of QTcpServer's signals you don't need to touch.
class A: public QObject
{
Q_OBJECT
public:
A() {};
virtual void doit() {
qDebug() << "A::doit";
emit foo(1);
emit bar(1);
}
signals:
void foo(int);
void bar(int);
};
Class B is your subclass. Notice that it redefines signal foo, but doesn't do anything to bar.
class B: public A
{
Q_OBJECT
public:
B() {};
virtual void doit() {
qDebug() << "B::doit";
emit foo(2);
emit bar(2);
}
signals:
void foo(int);
};
Class C is a potential client, connects the signals/slots from a B instance exactly like it would for an A instance.
class C: public QObject
{
Q_OBJECT
public:
C() {
B *b = new B;
connect(b, SIGNAL(foo(int)), this, SLOT(foo(int)));
connect(b, SIGNAL(bar(int)), this, SLOT(bar(int)));
/* 1 */
b->doit();
/* 2 */
b->A::doit(); // call parent class's function
};
public slots:
void foo(int i) {
qDebug() << "foo: " << i;
}
void bar(int i) {
qDebug() << "bar: " << i;
}
};
Here's the output from constructing a C:
B::doit // this is /* 1 */
foo: 2
bar: 2
A::doit // this is /* 2 */
bar: 1
... and nothing else. A's emit foo(1) isn't connected to C's foo slot, it will never arrive to C. A's emit bar(1) worked as expected, that signal is untouched.
With that setup, you can emit newConnection when your class is ready, QTcpServer's version of the signal will not be received by your user's objects.
To be a true drop in replacement, you probably will need to edit the actual source of Qt, because you normally can't reimplement any Private class calls.
If you are the only one using the replacement one, and you control the classes that connect to the newConnection signal...
Just connect newConnection to your own slot handleNewConnection. When the secure connection is ready emit myNewConnection and connect that to the elements that would have been connected to newConnection.
EDIT:
After a bit of digging, I found an option of to reconnect a signal:
http://qt-project.org/forums/viewthread/6820
Basically, you reimplement QObject::connect, and then you keep track of the connections and process them the way you need to. So in this case, you would keep a list of all the connections of the signal newConnection and keep it in a list so when you disconnect it you could reconnect it. Be sure to call QObject::connect at the end of the reimplementation.
Another option when going this route would be to go and just reroute the connections there. When a connection is requested from newConnection, move it there to myNewConnection.
Hope that helps.
A dirty hack would be to very briefly block the signals from QTcpServer. Since you know that newConnection() will be emitted right after you return from SslServer::incomingConnection(), call this->blockSignals(true); just before you return. That will prevent newConnection() from invoking any slots it is connected to.
To make sure you receive subsequent signals, unblock signals as soon as you can. I suppose the earliest time available would be right when control goes back to the event loop, so a QTimer::singleShot could do it.
void SslServer::incomingConnection(int socketDescriptor)
{
QSslSocket *serverSocket = new QSslSocket;
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
connect(serverSocket, SIGNAL(encrypted()), this, SLOT(ready()));
serverSocket->startServerEncryption();
} else {
delete serverSocket;
}
this -> blockSignals(true);
QTimer::singleShot(0, this, SLOT(unblockSignals());
}
void SslServer::unblockSignals()
{
this->blockSignals(false);
}
The downside of that is that you will lose every signal that could legitimately be emited between incomingConnection() and unblockSignals(). Like I said, it's a dirty hack.

How can I store and forward slots using boost::signals2?

I have a problem where I'm having to instantiate instances of objects
earlier than I would like to do so because I need to connect signal
slots through some deep ownership, and I'd like to come up with a way of
storing and forwarding the slots so that I can construct objects closer
to their use site, instead of doing so as member variables.
My basic problem is that I have a process that will download an update
file on a separate thread and send a progress signal to anyone who is
interested. The signal is essentially:
typedef boost::signals2::signal<void (double)> DownloadProgress;
Assume that the implementation of the progress function mentioned
below conforms to this; the nature of the signal itself isn't very
important (although I am using functors for the most part).
The signal is set and the code is called something like this:
Updater updater;
updater.onDownloadProgress(&progress);
updater.runDownloadTask();
When you call updater.runDownloadTask(), it will start the
UpdaterDownloadTask, which starts an HTTPRequest and returns an
HTTPResponse. The HTTPResponse is the piece which interacts with the
network layer and receives the data and contains the DownloadProgress
signal. With this, my implementation looks a bit like (bottom-up from
HTTPResponse, heavily abbreviated to elide methods that aren't
particularly illustrative):
class HTTPResponse
{
public:
// this will be called for every "chunk" the underlying HTTP
// library receives
void processData(const char* data, size_t size)
{
// process the data and then send the progress signal
// assume that currentSize_ and totalSize_ are properly set
progressSignal_(currentSize_ * 100.0 / totalSize_);
}
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
progressSignal_.connect(slot);
}
private:
DownloadProgress progressSignal_;
};
class HTTPRequest
{
public:
HTTPRequest() : response_(new HTTPResponse) { }
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
response_->connect(slot);
}
boost::shared_ptr<HTTPResponse> perform()
{
// start the request, which operates on response_.
return response_;
}
private:
boost::shared_ptr<HTTPResponse> response_;
};
class UpdaterDownloadTask : public AsyncTask
{
public:
DownloadTask() : request_(new HTTPRequest) { }
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
request_->connect(slot);
}
void run()
{
// set up the request_ and:
request_>perform();
}
private:
boost::shared_ptr<HTTPRequest> request_;
};
class Updater
{
public:
Updater() : downloadTask_(new UpdaterDownloadTask) { }
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
downloadTask_->onDownloadProgress(slot);
}
void runDownloadTask() { downloadTask_.submit() }
private:
boost::shared_ptr<UpdaterDownloadTask> downloadTask_;
};
So, my Updater has to have an instance of UpdaterDownloadTask that's
always around, which has an instance of HTTPRequest, which has an
instance of HTTPResponse—just because I have to forward the slot
connection from Updater (the public API entry point) to HTTPResponse
(where the signal belongs).
I would rather implement UpdaterDownloadTask::run() like so:
void run()
{
HTTPRequest request;
request.onDownloadProgress(slots_);
#if 0
// The above is more or less equivalent to
BOOST_FOREACH(const DownloadProgress::slot_type& slot, slots_)
{
request.onDownloadProgress(slot);
}
#endif
request.perform();
}
This would have similar implications at the HTTPRequest level (so I
don't have to construct the HTTPResponse until I perform the request)
and overall make for a nicer data flow with strong RAII semantics. I've
previously tried defining the slots_ variable as a vector:
std::vector<DownloadProgress::slot_type> slots_;
Yet I can only get this to work if I force the callers to call
onDownloadProgress(boost::ref(slot));.
Has anyone done this successfully, or have a good suggestion on how to
store and forward other than what I'm doing?
I think storing the slots in a vector should work ok. If you want to get rid of the need for boost::ref(...) you can remove the & from the onDownloadProgress parameter (since slot_type is copyable).
Alternatively, you could have your signal inside HTTPResponse fire and in turn fire a signal in HTTPRequest, doing that, you could connect all the slots to the signal in HTTPRequest, then once the HTTPResponse is created, you connect to the response signal onDownloadProgress(request.signalname). Where signalname is the signal your client.
pseudocode:
Request request;
request.onProgress(myProgressBarCallback);
//calls: this.signal.connect(myProgressBarCallback);
request.go();
//calls: Response response;
// and: response.onProgress(this.signal);
I hope that helps.