Delete thread with blocking function Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Ksawery
Experienced Solver
Experienced Solver
Posts: 83
Joined: Thu Jul 25, 2019 12:31 pm

Delete thread with blocking function

Post by Ksawery »

I currently have a function to delete and clean up all my threads when the application is closed (i'm using 3 wxThreads). Unfortunately one of the threads uses a blocking function call for incoming TCP/IP communication. The function will not return until communication is established, so in the case of no incoming connections, the wxThread will never be destroyed (as the while(TestDestroy()) condition will never be met). The thread never enters its destructor, and I'm unable to terminate the application correctly.

Is there a way to deal with this case in wxWidgets, or should I find a way to terminate the blocking function (it's from an external library - libmodbus, modbus_tcp_pi_accept() function). I was considering using the Kill() function to terminate the thread, but apparently its not safe.

Edit: the Kill() function doesn't help either.

Regards,
Ksawery
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Delete thread with blocking function

Post by doublemax »

I was considering using the Kill() function to terminate the thread, but apparently its not safe.
Can you set the length of the timeout? If not, Kill() is the only option. The main problem with this is that it can leak memory. But if happens only at app termination, that shouldn't be a problem.
Edit: the Kill() function doesn't help either.
Why not?
Use the source, Luke!
Ksawery
Experienced Solver
Experienced Solver
Posts: 83
Joined: Thu Jul 25, 2019 12:31 pm

Re: Delete thread with blocking function

Post by Ksawery »

I use the following code to terminate the thread:

Code: Select all

    //Delete TCP/IP thread
    {
        wxCriticalSectionLocker enter(mbThreadCS);
        if (mbThreadTCP)
        {
            if (mbThreadTCP->Kill() != wxTHREAD_NO_ERROR)
                wxLogError("Can't delete the thread!");
        }
    }

    while (1)
    {
        {
            wxCriticalSectionLocker enter(mbThreadCS);
            if (!mbThreadTCP) break;
        }
        wxThread::This()->Sleep(1);
    }
The application gets stuck in the while(1) loop, since the thread destructor is never called:

Code: Select all

cThreadTCP::~cThreadTCP()
{
    close(socket);
    free(tcpQuery);
    wxCriticalSectionLocker enter(mbGateway->mbThreadCS);
    mbGateway->mbThreadTCP = NULL;
}
Should I delete the pointer manually after using Kill()?

Regards,
Ksawery
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Delete thread with blocking function

Post by doublemax »

since the thread destructor is never called:
That's normal when you use Kill.
Should I delete the pointer manually after using Kill()?
Actually i'm not 100% sure about this. I wouldn't, but you can try what happens if you do.
Use the source, Luke!
alys666
Super wx Problem Solver
Super wx Problem Solver
Posts: 329
Joined: Tue Oct 18, 2016 2:31 pm

Re: Delete thread with blocking function

Post by alys666 »

you could not dream about correct killing thread if there is infinitely blocking function.
(that's why properly designed libraries MUST use timeouts).
variants
1. look if in your lib exists a timeouted function(often libs implement timeouted and not timeouted variants of the same function)
2. let your thread live till application end. he will die together with your application.
3. check if there could be a trick to send something to interface or device, to simulate incoming data, to resume blocked thread.

in reality in your sitaution case 2 is the most correct and simple.
bw the way, why tcp listening is not timeouted there???
ubuntu 20.04, wxWidgets 3.2.1
alys666
Super wx Problem Solver
Super wx Problem Solver
Posts: 329
Joined: Tue Oct 18, 2016 2:31 pm

Re: Delete thread with blocking function

Post by alys666 »

Ksawery wrote: Fri Oct 18, 2019 1:13 pm I use the following code to terminate the thread:

Code: Select all

    //Delete TCP/IP thread
    {
        wxCriticalSectionLocker enter(mbThreadCS);
        if (mbThreadTCP)
        {
            if (mbThreadTCP->Kill() != wxTHREAD_NO_ERROR)
                wxLogError("Can't delete the thread!");
        }
    }

    while (1)
    {
        {
            wxCriticalSectionLocker enter(mbThreadCS);
            if (!mbThreadTCP) break;
        }
        wxThread::This()->Sleep(1);
    }
The application gets stuck in the while(1) loop, since the thread destructor is never called:

Code: Select all

cThreadTCP::~cThreadTCP()
{
    close(socket);
    free(tcpQuery);
    wxCriticalSectionLocker enter(mbGateway->mbThreadCS);
    mbGateway->mbThreadTCP = NULL;
}
Should I delete the pointer manually after using Kill()?

Regards,
Ksawery
pointer just points to the thread you have killed. nobody will set it to null except of you.
you sit in second loop because of it.
you killed thread object inside heap, os and scheduler, but your pointer still is not null.
your logic is wrong. just kill it and forget.
ps...
as doublemax i also not sure will Kill delete the thread object or not. seems not. because thread can be allocated statically.
if thread is "detached", then Kill MAYBE deallocates object.
Last edited by alys666 on Fri Oct 18, 2019 1:47 pm, edited 1 time in total.
ubuntu 20.04, wxWidgets 3.2.1
Ksawery
Experienced Solver
Experienced Solver
Posts: 83
Joined: Thu Jul 25, 2019 12:31 pm

Re: Delete thread with blocking function

Post by Ksawery »

I still get the following message, despite using Kill():

Code: Select all

15:41:27: Debug: 1 threads were not terminated by the application.
So I guess I can't do anything until the blocking function returns? Im undertand though, that the thread is terminated, and the heap resources are freed anyway, when the app closes?
Last edited by Ksawery on Fri Oct 18, 2019 1:46 pm, edited 1 time in total.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Delete thread with blocking function

Post by doublemax »

Is it possible that libmodbus created an internal thread that's still running? Check the total number of threads of your application in the task manager.

When i google for libmodbus, i see a function modbus_set_response_timeout. Can you use that in your case?
https://libmodbus.org/docs/v3.0.6/modbu ... meout.html
Use the source, Luke!
alys666
Super wx Problem Solver
Super wx Problem Solver
Posts: 329
Joined: Tue Oct 18, 2016 2:31 pm

Re: Delete thread with blocking function

Post by alys666 »

debugger must show all app threads and and their names.
ubuntu 20.04, wxWidgets 3.2.1
alys666
Super wx Problem Solver
Super wx Problem Solver
Posts: 329
Joined: Tue Oct 18, 2016 2:31 pm

Re: Delete thread with blocking function

Post by alys666 »

Ksawery wrote: Fri Oct 18, 2019 1:41 pm I still get the following message, despite using Kill():

Code: Select all

15:41:27: Debug: 1 threads were not terminated by the application.
So I guess I can't do anything until the blocking function returns? Im undertand though, that the thread is terminated, and the heap resources are freed anyway, when the app closes?
app closing returns everything to OS. app works in virtual memory space, when you exit app, all threads will be killed, and all memory used by app will be marked as free.
ubuntu 20.04, wxWidgets 3.2.1
Ksawery
Experienced Solver
Experienced Solver
Posts: 83
Joined: Thu Jul 25, 2019 12:31 pm

Re: Delete thread with blocking function

Post by Ksawery »

Here are the threads running in the application:

Code: Select all

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffddc8) at ../cPomiarWiazki.cpp:3
3       wxIMPLEMENT_APP(cPomiarWiazki);
[New Thread 0x7fffeb904700 (LWP 3993)]
[New Thread 0x7fffeb103700 (LWP 3994)]
[New Thread 0x7fffea3f1700 (LWP 3996)]
[New Thread 0x7fffe9bf0700 (LWP 3997)]
[New Thread 0x7fffe93ef700 (LWP 4001)]
[New Thread 0x7fffe8a70700 (LWP 4002)]
[Thread 0x7fffe8a70700 (LWP 4002) exited]
There are more threads than I explicitly create, so I guess some must belong to libmodbus. I'm not sure how to terminate those.

Regards,
Ksawery
alys666
Super wx Problem Solver
Super wx Problem Solver
Posts: 329
Joined: Tue Oct 18, 2016 2:31 pm

Re: Delete thread with blocking function

Post by alys666 »

cough...cough... it's definitely not linux :)
there is nothing in thread list, but addresses only ...
1. if your lib has internal threads and has not explicit functions kinda
stop_lib, terminate... you must not try to stop something inside it.
there is no big problem if you closed app with still working thread(s), OS will kill app process with his local threads.
in my apps I finish my threads, but app has other threads and who finishes them - it's not my business.

ps.
in reality you will have
1. mainthread(where you started main of you app)
2. some additional internal threads of system libs and wxWIdgets.
under linux i have : 3 system threads+main+created by me.
ubuntu 20.04, wxWidgets 3.2.1
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Delete thread with blocking function

Post by doublemax »

Asking a 3rd time: Are you sure you can't set the timeout for the blocking function? That would solve everything.
Use the source, Luke!
Ksawery
Experienced Solver
Experienced Solver
Posts: 83
Joined: Thu Jul 25, 2019 12:31 pm

Re: Delete thread with blocking function

Post by Ksawery »

cough...cough... it's definitely not linux
What do you mean, this is under Linux Mint, Eclipse IDE :D
if your lib has internal threads and has not explicit functions kinda
stop_lib, terminate... you must not try to stop something inside it.
I don't think the library provides any way to interact with internal threads, although some people have suggested solutions:

https://github.com/stephane/libmodbus/issues/173
Asking a 3rd time: Are you sure you can't set the timeout for the blocking function? That would solve everything.
Unfortunately, I don't think there is a way to set the timeout.

I will try some of the suggested solutions on Monday. If these won't work, I will just allow the OS to terminate any threads when the App closes.

Many thanks,
Ksawery
Ksawery
Experienced Solver
Experienced Solver
Posts: 83
Joined: Thu Jul 25, 2019 12:31 pm

Re: Delete thread with blocking function

Post by Ksawery »

I managed to find (what I hope is) a good solution to the problem, by following these recommendations:

https://github.com/stephane/libmodbus/issues/452

I made the TCP/IP socket non-blocking, using the following function:

Code: Select all

fcntl(socket, F_SETFL, fcntl(socket, F_GETFL, 0) | O_NONBLOCK);
This effectively makes the modbus_tcp_pi_accept() function non-blocking as well. The only downside to this, is that I need to poll the function repeatedly for new connections, which will use more CPU resources. However, as I understand from your previous recommendations, adding wxThread::This()->Sleep(1) in an "infinite" thread partially alleviates using too much CPU?

There is another TCP/IP function which is blocking: modbus_receive(). This function blocks the thread when a connection is established, but no messages are being received. Fortunately, a timeout for this function was provided, due to many user requests:

https://github.com/stephane/libmodbus/issues/95

So now i'm successfully able to terminate the thread, using the recommended code:

Code: Select all

    //Delete TCP/IP thread
    {
        wxCriticalSectionLocker enter(mbThreadCS);
        if (mbThreadTCP)
        {
            if (mbThreadTCP->Delete() != wxTHREAD_NO_ERROR)
                wxLogError("Can't delete the thread!");
        }
    }

    while (1)
    {
        {
            wxCriticalSectionLocker enter(mbThreadCS);
            if (!mbThreadTCP) break;
        }
        wxThread::This()->Sleep(1);
    }
Many thanks,
Ksawery
Post Reply