[Interest] Calling QT Class method from pthread thread

Gonzalo Aguilar Delgado gaguilar at aguilardelgado.com
Wed Oct 4 16:32:48 CEST 2017


Hi Tony,

Forget about the blockingqueuedconnection it never does the emit. So 
will never arrive to the target. You can set any kind of delivery that's 
supported by QT it will fail a lot before. While doing the emit. This 
value was left behind just to test different things. The real queue used 
is QueuedConnection.

Thank you for the clarification.

Best regards,


On 04/10/17 15:45, Tony Rietwyk wrote:
>
> Hi Gonzalo,
>
> I don't think the documentation is clear enough, but my assumption is 
> that emitting a signal connected with BlockingQueuedConnection can 
> only be done in a thread created by QThread that has called 
> QThread.exec in its run override. Does your callback thread really 
> have to wait for the main thread to finish executing its slot? If not, 
> then I think just using QueuedConnection should work from a non-QThread.
>
> Regards, Tony
>
>
> On 4/10/2017 10:08 PM, 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
>
> _______________________________________________
> 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/65f44231/attachment.html>


More information about the Interest mailing list