Issue with the thread



  • Hello,
    I am running two threads one for fetching the frame and one for processing the frame.
    Given below is the signal and slot connection for handling the threads.
    Processing the frames:

    connect(processFrame,SIGNAL(workRequested()), threadProcessFrame, SLOT(start()));
    connect(threadProcessFrame, SIGNAL(started()), processFrame, SLOT(doWork()));
    connect(processFrame, SIGNAL(finished()), processFrame, SLOT(requestReWork()));
    connect(processFrame, SIGNAL(resumeWork()), processFrame, SLOT(doReWork()));
    connect(processFrame, SIGNAL(retrying()),processFrame,SLOT(requestReWork())); 
    

    Capturing the frames:

    connect(camera,SIGNAL(workRequested()), threadCamera, SLOT(start()),Qt::DirectConnection);
    connect(threadCamera, SIGNAL(started()), camera, SLOT(doWork()),Qt::DirectConnection);
    connect(camera,SIGNAL(frame(cv::Mat)),this,SLOT(updateFrame(cv::Mat)),Qt::DirectConnection);
    connect(camera, SIGNAL(finished()),threadCamera,SLOT(quit()),Qt::DirectConnection);

    My issue is the thread to process the frame is working fine but the capture frame is causing the program to break. I tried using try catch statement but it does not throw any exception.

    Only difference which i observe in the thread is process thread is continuously trying to run after frequent intervals where as in case of capturing i am trying to create a new thread.
    Also the thread is invoked when a request for camera frame is initiated.
    The line which is giving issue as per the logs is:
    camera->GrabOne(100,ptrGrabResult,TimeoutHandling_ThrowException);
    Also if i try to capture the frame without threading it is working fine.
    Every time when the request to get frame is made below call is make.
    camera->requestWork();

    I was doubtful whether telling the thread to quit and then requesting the frame is causing the issue?
    But if the above is the case the number of times which i get the frame is uneven means the thread my run 2 times or sometimes even 6 to 7 times.
    Please Note: I am using basler camera.


  • Qt Champions 2018

    @Kira said in Issue with the thread:

    but the capture frame is causing the program to break

    What do you mean by that? Do you mean it crashes? If so what is the error? SIGSEGV? Something else? Did you try to run through debugger to see the stack trace after crashing?



  • @jsulm : Actually the camera class has following line
    camera->GrabOne(100,ptrGrabResult,TimeoutHandling_ThrowException);
    where my program terminates.
    Actually my one lib file is compiled in release mode so when i try to run the program in debug mode i get error message as unable to initialize the gdb.


  • Qt Champions 2018

    @Kira Did you check that camera is a valid pointer at that time?
    And what type of crash is it? SIGSEGV or something else?



  • @jsulm said in Issue with the thread:

    Did you check that camera is a valid pointer at that time?
    -> How to check it?

    And what type of crash is it? SIGSEGV or something else?
    -> Have no idea. I try using the try catch but did not get any exception.


  • Qt Champions 2018

    @Kira try/catch will not help here.
    If you start your app from QtCreator then simply look in "Application Output" tab.
    Also you did not answer the question regarding camera pointer, so again - is camera a valid pointer?



  • @jsulm : Yes camera is a valid pointer.
    Also what i have observed that when i run the frame processing thread continuously it is creating the issue.
    When i only run the frame capture thread everything is fine.
    Once again would like to highlight this:

    connect(threadProcessFrame, SIGNAL(started()), processFrame, SLOT(doWork()));
    connect(processFrame, SIGNAL(finished()), processFrame, SLOT(requestReWork()));
    connect(processFrame, SIGNAL(resumeWork()), processFrame, SLOT(doReWork()));
    connect(processFrame, SIGNAL(retrying()),processFrame,SLOT(requestReWork()));

    Do you thing running the thread indefinately using the requestReWork slot is causing the issue?
    connect(processFrame, SIGNAL(finished()), processFrame, SLOT(requestReWork()));


  • Qt Champions 2018

    @Kira said in Issue with the thread:

    connect(processFrame, SIGNAL(finished()), processFrame, SLOT(requestReWork()));

    Actually this thread should not finish until you terminate it. Instead it should wait for new work package coming in via signal/slot.



  • @jsulm : Hi i was just analysing the code and found out that may be process frame thread is still executing when the capture frame is invoked.
    Work around: I replaced the camera function with reading a image from the disk but still the issue occured. So i concluded that it cannot be issue of camera.
    I also observed that frame processing thread was still executing when camera Thread is called program terminated with log that thread was invoke.
    Though the two threads are independent may be something is conflicting.
    How can i make them independent ??


  • Qt Champions 2018

    @Kira Maybe you should have a queue for work packages where you put work packages and the processing thread takes next package when it finishes one?



  • @jsulm : I think i have figured where exactly the issue is:
    If suppose the processFrame thread is working camera request a frame and processframe haven't finished working. Below signal will will be generated:
    connect(workerPrimaryCamera,SIGNAL(workRequested()), threadPrimaryCamera, SLOT(start()),Qt::DirectConnection);
    And since it is Qt::DirectConnection it will immediately try to invoke slot causing a conflict and somehow cause a crash.
    What do you think ?
    Actually as per my program requirements i have to get the frame from the camera when demanded.
    I can continuously fetch the frame in a thread but it is not acceptable as there are chances of getting older frame.
    Can you please suggest any sophisticated way to implement the same.
    Thanks


  • Qt Champions 2018

    @Kira said in Issue with the thread:

    Qt::DirectConnection

    I don't think this is a good idea when connecting signals/slots between different threads, should be queued connection.


  • Moderators

    @Kira said in Issue with the thread:

    And since it is Qt::DirectConnection it will immediately try to invoke slot causing a conflict and somehow cause a crash.
    What do you think ?

    it's worse than that, with a forced DirectConnection, the SLOT is executed in the calling thread.

    Without any QMutex or similar, this is highly likely the cause of your problems.



  • Hi @Kira !

    Yes, the Qt::DirectConnection is a problem with threads. You should make sure you are using the Qt::QueuedConnection and that you are passing a buffer of data that the processing thread can take ownership of and destroy when finished. I like to use QSharedData/QSharedDataPointer so the cleanup is scoped and easy.

    The nice thing about queued connections is that mutexing can be minimal when using the QSharedData/QSharedDataPointer (if at all) and the data will "queue" up so you can access it as fast as you need to.

    I process hundreds of GNSS and CAN messages per second so you should be OK.


  • Qt Champions 2017

    @Buckwheat said in Issue with the thread:

    Yes, the Qt::DirectConnection is a problem with threads.

    I object to that statement! I have a 5 years old or so C++ syntax parser that is threaded and uses direct connections exclusively. I would argue that one should know what Qt::DirectConnection implies, however. Same goes for Qt::QueuedConnection - just mindlessly using queued calls over whatever thread the objects happen to be in means you're just as mindlessly copying data around without a reason. What one should default to is the default - Qt::AutoConnection, and use a direct or a queued connection when and only when that's what is exactly, explicitly, supposed to happen.



  • @jsulm @J-Hilk @Buckwheat @kshegunov :
    Guys thanks for response. I problem seems to be with camera thread. Please have a look over the connections:
    connect(camera,SIGNAL(workRequested()), threadCamera, SLOT(start()),Qt::DirectConnection);
    connect(threadCamera, SIGNAL(started()), camera, SLOT(doWork()),Qt::DirectConnection);
    connect(camera,SIGNAL(frame(cv::Mat)),this,SLOT(updateFrame(cv::Mat)),Qt::DirectConnection);
    connect(camera, SIGNAL(finished()),threadCamera,SLOT(quit()),Qt::DirectConnection);

    I am following the following approch:
    Constructor:
    camera->moveToThread(threadCamera);
    Main Program:
    camera->requestWork() // At this point i initialite the thread to fetch frame
    what is did after few miiliseconds i again called camera->requestWork() without checking whether
    previous thread have been stopped.
    As i have used Qt::DirectConnection in all my slots other the first thread used to work forcing other thread to wait but this logic seems to fail at certain instance of time and the program would crash.
    If i remove Qt::DirectConnection the slots don't respond.

    1. Please let me know correct way in which i can call the thread ?
    2. Is not correct to call camera->workRequest multiple time ?
    3. Does calling camera->workRequest multiple time creates multiple instance or same thread instance is called everytime?

  • Qt Champions 2017

    @Kira said in Issue with the thread:

    If i remove Qt::DirectConnection the slots don't respond.

    You're blocking the event loop for that to occur. Don't block the event loop and you're going to be fine. Search the forums, I, personally, have written many posts on that particular topic, so the information is in there.



  • @kshegunov : I have diabled my tensorflow library for my debugger to work.
    I am getting the following exception from the thread.

    0_1559540018003_c1cd8e53-93fc-4d9c-853a-a47154b896ee-image.png

    Add debugger shows error at following line of alloc.h:
    uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN);


  • Qt Champions 2017

    With 98% certainty you have an infinite recursion somewhere. Where and how is beyond me.



  • @kshegunov : Finally resolved and learnt the importance of debugger in life.
    I just commented the tensorflow lib which was a release mode lib and was causing the gdb error.

    Exact Issue:
    I have created a QPair which in which i inserted a image with a processed flag set to false.
    My tread whereas in background would run independently and try to process the image and set the processed flag to true.
    There was a condition in my loop where led the thread to access a certain location which was not present in the QPair list and caused the trigger to terminate abnormally.
    Thanks to the debugger the issue was clear.



  • @kshegunov said in Issue with the thread:

    @kshegunov I am glad you take offense. But, the default behavior for connection seems to be queued connection when crossing thread boundaries. I have found NO exception to this in the last 7 years so obviously the Qt designers thought there might be a problem. This queuing is why you can Q_EMIT data from a thread and put it into a GUI control which can only be done from the main thread. Also, I just said "Qt::QueuedConnection is no problems with threads". I would assume he is using the defaults in his thread.

    As for copying, Sending a QSharedDataPointer is 4 bytes and is reference counted. NO COPYING except a pointer. Please read carefully before making "mindlessly" making judgements.

    As 99% of my posts say, it is all in your design. Know what you are doing and what protections are offered. If you need to queue packets, QSharedDataPointer is great and it manages the pointers properly.

    So, in summary, feel as offended as you like. It is a free forum and we can react how we like!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.