Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Segmentation fault while emitting signal from other thread in Qt

When I am trying to emit a signal from another thread it causes a segfault, not sure why.
Both the signal and slot are defined in the same class and running under the main GUI thread, but I call the emit in another function which is being controlled by a boost thread type of thread.

I am using Qt4 and Ubuntu 10.04 is my OS. This function is called from another thread which is emitting the signal.

    void MyMapItem::updateMap(std::vector<int> data11)
{
my_mutex.lock();    
cout<< "i am in updatemap"<<endl;
data12.clear();
data12=data11;
cout<<"size of data"<<data12.size()<<endl;
my_mutex.unlock();
emit mera_signal();
}

    MyMapItem::MyMapItem(QGraphicsItem *parent )
{

    QObject::connect(this,SIGNAL(mera_signal()),this,SLOT(mera_slot()),Qt::BlockingQueuedConnection );



}

Here above is my constructor of Qt class.

void MyMapItem::mera_slot()
{
cout<< "signal is emitted"<<endl;
qDebug() << "Date:";
} 

And above is the slot definition I am just printing a message for the time being.

Let me elaborate my flow a little bit more.

  1. I have one class MapGenerator which is inherited from QThread now, which is connected to ROS and subscribing to a topic.
  2. Now I get another class MyMapitem which is inherited from QObject and GraphicsItem both and in this class I have defined a slot and a signal.
  3. Now I got a third class Mainwindow which is inherited from Qobject and setting up the graphicsscene for me taking mymapitem.
  4. Now what I do in main is to make object of Mapgenerator and start the thread.
  5. Then I make an object of Mainwindow.
  6. So when Mapgenerator thread starts it subscribes data from ROS and calls a function in MyMapItem and transfer data there.

Here I want to emit a signal so I know that new data arrived. Then I update the item which is already in the scene there in the Mainwindow constructor. The connection is made in MyMapItem class constructor.

Thanks Here i post my main method where i am creating the thread and main window.

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ros::init(argc,argv,"last");
    MapGenerator::MapGenerator mg(argc,argv);
    //boost::thread ros_thread(boost::bind(&MapGenerator::init2, &mg));
    mg.start(); // Qthread 
    MainWindow w(argc,argv);
    w.show();
    return a.exec();
}

here in Main window constructor i made Mapitem object

MainWindow::MainWindow( int argc, char **argv, QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("My app");
    mapitem = new MyMapItem();
    scene = new QGraphicsScene(0,0,4000,4000);
    ui->graphicsView->setScene(scene);
    scene->addItem(mapitem);
}
like image 417
TopGun Avatar asked Dec 31 '25 19:12

TopGun


1 Answers

When you are setting up the class, which often involves connecting signals to slots, you have the option to specify a connection type.

bool QObject::connect ( const QObject * sender, const char * signal,
const QObject * receiver, const char * method,
Qt::ConnectionType type = Qt::AutoConnection ) [static]
________________ <--- specify your connection type as one of the queued ones

The default value, Qt::AutoConnection relies on QThread stuff to know if the signal is coming from the same thread or a different one. Since you're not using QThreads, you can't rely on this. Explicitly tell the connection to be made as QueuedConnection or BlockingQueuedConnection depending on how you want it to behave in the calling thread (see the link for details).

If for some reason you find it inappropriate to set the connection to one of these types all the time, you can also utilize QMetaObject::invokeMethod to call in from a different thread. Notice that this function also allows you to specify a connection type:

Invokes the member (a signal or a slot name) on the object obj. Returns true if the member could be invoked. Returns false if there is no such member or the parameters did not match. The invocation can be either synchronous or asynchronous, depending on type:

If type is Qt::DirectConnection, the member will be invoked immediately.

If type is Qt::QueuedConnection, a QEvent will be sent and the member is invoked as soon as the application enters the main event loop.

If type is Qt::BlockingQueuedConnection, the method will be invoked in the same way as for Qt::QueuedConnection, except that the current thread will block until the event is delivered. Using this connection type to communicate between objects in the same thread will lead to deadlocks.

If type is Qt::AutoConnection, the member is invoked synchronously if obj lives in the same thread as the caller; otherwise it will invoke the member asynchronously.

like image 196
tmpearce Avatar answered Jan 04 '26 05:01

tmpearce



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!