lwip_close on master esp-idf

warmcat
Posts: 2
Joined: Sat Mar 11, 2017 7:11 am

lwip_close on master esp-idf

Postby warmcat » Sat Mar 11, 2017 7:22 am

Hi -

With esp-idf 4745895e229d8e1ca4e6f4b601397c0ba0b3d2db, close(socket_fd) ends up in lwip_close() okay. That does netconn_delete() OK. Currently, freeing the socket is skipped though.

#if !ESP_THREAD_SAFE
free_socket(sock, is_tcp);
#endif

I assume it's supposed to be done lazily later.

But any closed fd's are not made available for reuse, the next fd to open monotonically increases until we run out of space to map them.

Is this because the lazy fd freeing thread cannot run, or something else?

On a normal posix system the fd is freed and then the lowest free fd is used for each new open / socket, but that does not happen here.

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: lwip_close on master esp-idf

Postby kolban » Wed Mar 15, 2017 5:30 am

I tried to find this code in the current ESP-IDF master but was not able to quickly find it. Can you find the same logic in the ESP-IDF master found here https://github.com/espressif/esp-idf?

It may be that what you can concerned about has been resolved in the latest releases?
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: lwip_close on master esp-idf

Postby ESP_Angus » Wed Mar 15, 2017 6:45 am

Hi warmcat,

Two things are happening here, but they're not related (although I see how it seems they are.)
  • The ESP_THREAD_SAFE modifications are to handle the case where a socket may be in use in a different task. For example, Task A has called recv() on the socket while the Task B calls close(). Freeing the socket's memory immediately is not possible, because Task A is still blocked inside lwip_recv() waiting for data. A reference counting approach is used. After a socket is "closing", it will be freed when its reference count goes to zero.
  • LWIP doesn't allocate FDs in the same way that Linux does. You can have up to NUM_SOCKETS (CONFIG_LWIP_MAX_SOCKETS in ESP-IDF) different file descriptor values. The table of these is statically allocated as an array of pointers (the 'sockets' array in sockets.c). The actual connection data (the structure pointed to by each pointer in 'sockets') is dynamically allocated when the socket is opened. The FD selection algorithm will preference choosing a brand new FD value ('sockets' table index) which has never been used, over one which has been used and then freed. Once all FDs have been used once, it will choose the "oldest" FD (ie the one which has been closed for the longest time.) Check the "alloc_socket()" function in sockets.c for the implementation of this algorithm.
The FD selection algorithm may seem odd but it's quite useful when debugging or reviewing log output, because if you see some fd value X which is closed then you know that there won't be a new socket with the same fd X for a while afterwards.

Who is online

Users browsing this forum: ccrause and 257 guests