How to implement tcp_sent callback ?

salocinx
Posts: 8
Joined: Sat Dec 22, 2018 12:54 am

How to implement tcp_sent callback ?

Postby salocinx » Mon Mar 30, 2020 1:31 pm

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!

ESP_Sprite
Posts: 9757
Joined: Thu Nov 26, 2015 4:08 am

Re: How to implement tcp_sent callback ?

Postby ESP_Sprite » Tue Mar 31, 2020 7:58 am

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.

salocinx
Posts: 8
Joined: Sat Dec 22, 2018 12:54 am

Re: How to implement tcp_sent callback ?

Postby salocinx » Tue Mar 31, 2020 10:49 am

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?

ESP_Sprite
Posts: 9757
Joined: Thu Nov 26, 2015 4:08 am

Re: How to implement tcp_sent callback ?

Postby ESP_Sprite » Tue Mar 31, 2020 7:02 pm

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.

salocinx
Posts: 8
Joined: Sat Dec 22, 2018 12:54 am

Re: How to implement tcp_sent callback ?

Postby salocinx » Mon Apr 06, 2020 11:32 am

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.

salocinx
Posts: 8
Joined: Sat Dec 22, 2018 12:54 am

Re: How to implement tcp_sent callback ?

Postby salocinx » Mon Apr 06, 2020 9:29 pm

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.
Last edited by salocinx on Thu Apr 09, 2020 10:24 am, edited 1 time in total.

ESP_Sprite
Posts: 9757
Joined: Thu Nov 26, 2015 4:08 am

Re: How to implement tcp_sent callback ?

Postby ESP_Sprite » Wed Apr 08, 2020 1:13 pm

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?

salocinx
Posts: 8
Joined: Sat Dec 22, 2018 12:54 am

Re: How to implement tcp_sent callback ?

Postby salocinx » Tue Apr 14, 2020 12:45 pm

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!

Who is online

Users browsing this forum: No registered users and 361 guests