From bf8ceae78039280d1eeb9a5a3d1ac7dbaf02ff5c 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 d8c034bc0e..d1448142fa 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -1058,8 +1058,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; } _lock_acquire(&s_fd_table_lock);