Error when closing application. 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: 74
Joined: Thu Jul 25, 2019 12:31 pm

Error when closing application.

Post by Ksawery » Thu Mar 26, 2020 2:05 pm

Hello,

I'm writing a new mulithreaded application in wxWidgets, and I'm encountering a pointer/malloc error that I can't quite figure out. I'm not sure if the problem lies in my wxWidgets code, or the external library that I'm using.

On starting my wxWidgets application, I create an additional thread that runs in the background and handles Modbus communication (the application is the Modbus Master). The thread periodically triggers events in the main application window, which is then updated appropriately with new data etc. Everything works fine, until I close my application, which then throws the following error:

Code: Select all

munmap_chunk(): invalid pointer 
Here is the call stack:

Code: Select all

NaswietlanieWiazka [C/C++ Application]	
	NaswietlanieWiazka [16919] [cores: 2]	
		Thread #1 [NaswietlanieWia] 16919 [core: 2] (Suspended : Container)	
			futex_wait_cancelable() at futex-internal.h:88 0x7ffff2ca99f3	
			__pthread_cond_wait_common() at pthread_cond_wait.c:502 0x7ffff2ca99f3	
			__pthread_cond_wait() at pthread_cond_wait.c:655 0x7ffff2ca99f3	
			wxConditionInternal::Wait() at 0x7ffff6e373a3	
			wxThreadModule::OnExit() at 0x7ffff6e3d0b5	
			wxModule::DoCleanUpModules() at 0x7ffff6d98820	
			wxEntryCleanup() at 0x7ffff6d7d0bf	
			wxUninitialize() at 0x7ffff6d7d12c	
			wxEntry() at 0x7ffff6d7ddd8	
			main() at cEntry.cpp:3 0x5555555c522c	
		Thread #2 [gmain] 16935 [core: 2] (Suspended : Container)	
		Thread #3 [gdbus] 16936 [core: 2] (Suspended : Container)	
		Thread #4 [NaswietlanieWia] 16938 [core: 2] (Suspended : Signal : SIGABRT:Aborted)	
			__GI_raise() at raise.c:51 0x7ffff6330e97	
			__GI_abort() at abort.c:79 0x7ffff6332801	
			__libc_message() at libc_fatal.c:181 0x7ffff637b897	
			malloc_printerr() at malloc.c:5,350 0x7ffff638290a	
			munmap_chunk() at malloc.c:2,846 0x7ffff6389ecc	
			__GI___libc_free() at malloc.c:3,117 0x7ffff6389ecc	
			wxThread::~wxThread() at 0x7ffff6e36555	
			cThreadRTU::~cThreadRTU() at cModbus.cpp:76 0x5555555d109a	
			cThreadRTU::~cThreadRTU() at cModbus.cpp:82 0x5555555d10ca	
			DeleteThread() at 0x7ffff6e3b018	
			<...more frames...>	
		Thread #5 [pool] 16940 [core: 2] (Suspended : Container)	
	gdb (8.1.0.20180409)	
The error appears in Thread #4, in the wxThread class destructor. I'm not sure which pointer the error is referring to, i've double checked all of them.

Here is my code:

Constructor:

Code: Select all

cThreadRTU::cThreadRTU(cModbus *mbMaster) : wxThread(wxTHREAD_DETACHED)
{
    this->mbMaster = mbMaster;

    ctx = nullptr;
    ct = -1;

	//Create new RTU configuration
    ctx = modbus_new_rtu(mbMaster->pEntry->mbPort.mb_str(), MB_BAUD, 'E', 8, 1);
	modbus_set_slave(ctx, mbMaster->pEntry->mbAddress);
	modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS232);
	modbus_set_response_timeout(ctx, 1, 0);
	modbus_set_byte_timeout(ctx, 0, 100000);
	ct = modbus_connect(ctx);
}
Thread loop:

Code: Select all

wxThread::ExitCode cThreadRTU::Entry()
{
	//Read coils on initialization
	if (ct != -1)
	{
		wxCriticalSectionLocker enter(mbMaster->mb_guard);
		mbMaster->mb_mapping->tab_input_registers[10] = modbus_read_bits(ctx, 1, MB_NUM_COILS, mbMaster->mb_mapping->tab_bits);
	}

    while (!TestDestroy())
    {
        if (ct != -1)
        {
        	wxCriticalSectionLocker enter(mbMaster->mb_guard);
        	mbMaster->mb_mapping->tab_input_registers[11] = modbus_read_input_bits(ctx, 10001, MB_NUM_INPUT_BITS, mbMaster->mb_mapping->tab_input_bits);
        	mbMaster->mb_mapping->tab_input_registers[12] = modbus_read_input_registers(ctx, 30001, MB_NUM_INPUT_REGISTERS, mbMaster->mb_mapping->tab_input_registers);
        }

		if (mbMaster->pMain != nullptr)
		{
			//Send event to main window
			wxCommandEvent evt(wxEVT_RTU_UPDATE, wxID_ANY);
			((wxEvtHandler*) mbMaster->pMain)->AddPendingEvent(evt);
		}

        wxThread::Sleep(MB_SCANRATE);
    }



    return (wxThread::ExitCode) 0;
}
Call to destroy thread:

Code: Select all

void cModbus::CloseModbus(void)
{
    {
        wxCriticalSectionLocker enter(mb_guard);

        //Delete RTU thread
        if (mbThreadRTU)
        {
            if (mbThreadRTU->Delete() != wxTHREAD_NO_ERROR) wxLogError("Can't delete the thread!");
        }
    }

    while (1)
    {
        {
            wxCriticalSectionLocker enter(mb_guard);
            if (!mbThreadRTU) break;
        }
        wxThread::This()->Sleep(1);
    }
}
Thread class destructor (where the error occurs):

Code: Select all

cThreadRTU::~cThreadRTU()
{
    modbus_close(ctx);
	modbus_free(ctx);
    mbMaster->mbThreadRTU = NULL;
}
I'm using wxWidgets version 3.1.3.

Thank you in advance for your help.

Ksawery

Ksawery
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Jul 25, 2019 12:31 pm

Re: Error when closing application.

Post by Ksawery » Thu Mar 26, 2020 2:15 pm

Upon further investigation, it seems that these function calls - in the Thread loop - are causing the error when closing the app for some reason:

Code: Select all

if (ct != -1)
{
	wxCriticalSectionLocker enter(mbMaster->mb_guard);
	mbMaster->mb_mapping->tab_input_registers[11] = modbus_read_input_bits(ctx, 10001, MB_NUM_INPUT_BITS, mbMaster->mb_mapping->tab_input_bits);
	mbMaster->mb_mapping->tab_input_registers[12] = modbus_read_input_registers(ctx, 30001, MB_NUM_INPUT_REGISTERS, mbMaster->mb_mapping->tab_input_registers);
}
What is weird however, is that they shouldn't be called when the thread is terminated. Am I doing something wrong when terminating the thread?

Many thanks,
Ksawery

Ksawery
Experienced Solver
Experienced Solver
Posts: 74
Joined: Thu Jul 25, 2019 12:31 pm

Re: Error when closing application.

Post by Ksawery » Thu Mar 26, 2020 2:38 pm

Ok, I've found the problem, apologies for the long post, but it had me confused for a while.

The memory location I was referring to in:

Code: Select all

mbMaster->mb_mapping->tab_input_registers[11]
was not created correctly, and hence the pointer errors, coming from the external Modbus library. I'm not sure why the application didn't report the error when running normally. The debugger didn't make it easy to find the problem either.

Anyway, sometimes it's helpful to write things out in a forum post to figure it out.

Many thanks,
Ksawery

Post Reply