[Interest] Calling QT Class method from pthread thread

Gonzalo Aguilar Delgado gaguilar at aguilardelgado.com
Wed Oct 4 17:32:03 CEST 2017


Hello,

I moved from that solution that's not working to another approach I've 
used in other projects. It's like the pooled mechanism used by Qt to 
send signals. I've created a Queue with QQueue.

The callback only has to put a new message to be processed in the queue.

The class that was previously MQMessageManager is now a thread that 
takes elements from the queue to process them.

What's my surprise? It also failed!!!! Appart from the fact I didn't 
mutexed the access...


The inferior stopped because it received a signal from the operating system.

Signal name :

	

SIGSEGV

Signal meaning :

	

Segmentation fault

Here inside QList...

// This violates pointer aliasing rules, but it is known to be safe (and 
silent)// in unoptimized GCC builds (-fno-strict-aliasing). The other 
compilers which// set the same define are assumed to be safe.else 
*reinterpret_cast<T*>(n) = t;

I'm starting to thing the election of this framework was not a good 
idea. C'mon...


On 04/10/17 13:08, Gonzalo Aguilar Delgado wrote:
>
> Hello,
>
> I'm facing a problem that don't know how to tackle. I created a 
> library that runs on C. It's based on callbacks and it seems to work 
> in other projects well.
>
> When connecting to Qt and classes I found a couple of problems that 
> now they are extending.
>
> It seems that I cannot set a callback from C directly to a class, so I 
> created an intermediate static function that will wrap the call to the 
> class.
>
> static gboolean callbackWrapper(SG64ZeroMQ* mq, ThriftStruct* message, 
> gpointer data, GError **error) {    qDebug("Message received");    
> MQMessageManager *self = static_cast<MQMessageManager*>(data);    
> fflush(stdout);    qDebug("Thread of the call %x", 
> QThread::currentThread());    self->processMessage(mq, message, 
> error);    return TRUE;}
>
> Nice. We get the class from the callback. Do a static cast and go 
> ahead with processing. But I want to notify other class that a event 
> happend, with a Signal.
>
> For completeness I include also constructor.
>
> MQMessageManager::MQMessageManager() 
> :error(NULL),mqsubscriber(NULL){qDebug("Thread of the class %x", 
> QThread::currentThread());}
>
> bool MQMessageManager::processMessage(SG64ZeroMQ* mq, ThriftStruct* 
> message, GError **error){    mqPayload *payload=NULL;    mqCardEvent 
> *cardEvent = NULL;    mqMessage *msg=NULL;    QString str;    
> g_return_val_if_fail (THRIFT_IS_STRUCT (message), FALSE);    
> if(IS_MQ_MESSAGE(message))      msg=MQ_MESSAGE(message);    
> switch(msg->type){      case MQ_MESSAGE_TYPE_COMMAND:        
> puts("Received a command");        break;      case 
> MQ_MESSAGE_TYPE_GPS_EVENT:        puts("Received a gps event");        
> break;      case MQ_MESSAGE_TYPE_CARD_EVENT:        
> if(IS_MQ_CARD_EVENT(msg->payload->card_event)){            cardEvent = 
> msg->payload->card_event;            if(cardEvent!=NULL && 
> cardEvent->atr!=NULL){                QByteArray array((char 
> *)cardEvent->atr->data, (int) cardEvent->atr->len);                
> QString atr = QString(array.toHex());                qDebug("ATR found 
> of size %d, %s", cardEvent->atr->len, 
> atr.toLatin1().data());*                emit 
> cardValidationSuccess();****                qDebug("Emitted valid 
> signal");*            }        }        break;      default:        
> printf("Message of type %i cannot be managed\n", msg->type);        
> break;    }    return TRUE;}
>
> Of course I did the typical connect signals functions. Done in the 
> MainWindow.cpp class. After object creation and all the stuff.
>
>     qDebug("Thread of the connect %x", QThread::currentThread());    
> if(!QObject::connect(mqMessageManager, 
> SIGNAL(cardValidationSuccess()), this, 
> SLOT(displayValid()),Qt::QueuedConnection)){        qDebug("Cannot 
> connect signal");    }    QObject::connect(mqMessageManager, 
> SIGNAL(valid(QString)), this, SLOT(displayValid(QString)), 
> Qt::BlockingQueuedConnection);
>
> Well, when the emit is called the system blows up!
>
> My investigations tells me that since the emit is called from the 
> callback thread and the class was created in another thread there's a 
> problem there that avoids the system to correctly function. The 
> problem is that everyone tells me that signal emission doesn't has 
> anything to do with thread affinity. I don't think so with the proof 
> in my hand.
>
> When you run the code the log is shown like this:
>
> Thread of the class 557845a0
>
> Starting ticketing
>
> Thread of the connect 557845a0
>
> Connecting localhost
>
> Connected to server
>
> Message received
>
> Thread of the call c00024f0
>
> ATR ...
>
> ---Crash on emit---
>
> The question is. Is there any way to run self->processMessage(mq, 
> message, error); On the same thread the class was defined 0x557845a0 
> instead of the calling thread 0xc00024f0?
>
> I defined process message like a slot. But if I use invokeMethod it 
> also crash when calling it. I suppose because the same issue. 
> moveToThread also doesn't work and it fails, I suppose because the 
> same problem.
>
> The root of the issue to me is that a pthread doesn't have all the 
> information that QT injects into the software and it makes everything 
> run there to blow up when using QT mechanism. Since the support is not 
> enable on that thread.
>
> Any help on this?
>
> Best regards,
>
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20171004/e54074e6/attachment.html>


More information about the Interest mailing list