Page 1 of 1

How to implement tcp_sent callback ?

Posted: Mon Mar 30, 2020 1:31 pm
by salocinx
Hi. I am a quite noob with C and ESP-IDF, but I managed to implement my own TCP protocol which let me communicate between a Java application and the ESP32. The application runs most of the time fine, but sometimes I get a heap corruption message. I believe this is because I am using a queue that manages pointers to a larger "network packet" struct. The heap corruption could occur because I free the memory for the outgoing "network packet" object as soon as the TCP socket's send() function returns. But I believe, that returning from the send() function not always means that the bytes are already completely sent. Therefore releasing the memory immediately after send() returns, can cause the heap corruption error (at least in my limited theory).

In order to prove/disprove my theory, I wanted to implement the lwIP's tcp_sent() callback function and releasing the memory reserved for the "network packet" object there. But I was not able to do it. Could somebody please tell me how I can implement this function? Best would be to extend the ESP-IDF TCP server socket example, since my code is based on that example.

Thank you!

Re: How to implement tcp_sent callback ?

Posted: Tue Mar 31, 2020 7:58 am
by ESP_Sprite
Your theory is wrong; send() does not take away your ownership of the data being sent and as soon as send() returns you can modify or delete the buffer.

Re: How to implement tcp_sent callback ?

Posted: Tue Mar 31, 2020 10:49 am
by salocinx
Thanks for your answer! I meanwhile update the ESP-IDF to the latest master-branch and the problem has gone away. Was there a bug-fix in the lwIP package lately?

Re: How to implement tcp_sent callback ?

Posted: Tue Mar 31, 2020 7:02 pm
by ESP_Sprite
Nothing that causes a heap corruption I know of, but to be honest I don't know all the bugfixes made in ESP-IDF. The other explanation is that there still is some bug (either in your code or in esp-idf) but updating just doesn't cause it to trigger a heap corruption anymore.

Re: How to implement tcp_sent callback ?

Posted: Mon Apr 06, 2020 11:32 am
by salocinx
Thanks for your response. You're right, the heap corruption came back. It's quite strange, sometimes the heap corruption appears often, sometimes everything works fine.

I meanwhile consulted the Heap Memory Debugging documentation and enabled "Comprehensive" mode for heap memory debugging via sdkconfig.

I get the following error information:

Code: Select all

CORRUPT HEAP: Bad tail at 0x3ffcc400. Expected 0xbaad5678 got 0xbaad56fb
abort() was called at PC 0x40082aaa on core 1
Subsequently I searched for the symbol information using xtensa-esp32-elf-gdb providing my application *.elf file. I looked up program counter address: 0x40082aaa

Code: Select all

PC 0x40082aaa: lock_acquire_generic + 66 in section .iram0.text
That doesn't help me a lot. Have you some advice on how I could further track down this issue?

PS.: The corruption seems to appear around the TCP send() function.

Re: How to implement tcp_sent callback ?

Posted: Mon Apr 06, 2020 9:29 pm
by salocinx
I maybe found the cause for the heap corruption, although I don't understand why. The struct described in the original post had a flexible array at the end. I now replace it with a fixed-size array. Now the program runs very stable. Here's the struct I used before:

Code: Select all

typedef struct mb32_packet_t {
	uint16_t preamble;
	uint8_t  system_id;
	uint8_t  message_id;
	uint8_t  reserved;
	uint16_t checksum;
	uint32_t pay_len;
	uint8_t  payload[];
} __attribute__((packed)) mb32_packet_t;
This is the new struct:

Code: Select all

typedef struct mb32_packet_t {
	uint16_t preamble;
	uint8_t  system_id;
	uint8_t  message_id;
	uint8_t  reserved;
	uint16_t checksum;
	uint32_t pay_len;
	uint8_t  payload[512];
} __attribute__((packed)) mb32_packet_t;
Without any other changes regarding malloc() and free(), it now works very stable.

I have started another thread on the FreeRTOS forums discussing this issue.

Re: How to implement tcp_sent callback ?

Posted: Wed Apr 08, 2020 1:13 pm
by ESP_Sprite
FreeRTOS shouldn't care about that: a pointer is a pointer is a pointer. The heap debugging message does however hint at something writing exactly one byte past the end of the allocated memory region; perhaps you have an off-by-one error somewhere?

Re: How to implement tcp_sent callback ?

Posted: Tue Apr 14, 2020 12:45 pm
by salocinx
Hi ESP_Sprite. Thanks a lot for your analysis. This can be very well. I am allocating memory and subsequently assign some bytes to it. Among other things, also a null-terminated C string. Perhaps I have some bug with the null terminator. I am currently in the process of refactoring my application and I will take a closer look. Many thanks for your help!