From b972b442e0505fd864527b6c84a70efc50dd1eae Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 6 May 2022 14:40:12 +0200 Subject: [PATCH] vfs: Fix potential select() race if both sock and other-fd trigger This fixes a potential race condition in select() if both a socket-fd and non-socket fd trigger simultaneously to unblock this select. In case of both fds, we use lwip's local thread semaphore, so we only have to try return it (if it was taken/triggered more than once) when we exit select(). Closes https://github.com/espressif/esp-idf/issues/8896 --- components/vfs/vfs.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index 4b997ea66b..08ec576820 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -1006,8 +1006,16 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds if (ret >= 0) { ret += set_global_fd_sets(vfs_fds_triple, vfs_count, readfds, writefds, errorfds); } - if (sel_sem.is_sem_local && sel_sem.sem) { - vSemaphoreDelete(sel_sem.sem); + if (sel_sem.sem) { // Cleanup the select semaphore + if (sel_sem.is_sem_local) { + vSemaphoreDelete(sel_sem.sem); + } else if (socket_select) { + SemaphoreHandle_t *s = sel_sem.sem; + /* Select might have been triggered from both lwip and vfs fds at the same time, and + * we have to make sure that the lwip semaphore is cleared when we exit select(). + * It is safe, as the semaphore belongs to the calling thread. */ + xSemaphoreTake(*s, 0); + } sel_sem.sem = NULL; } free(vfs_fds_triple);