瀏覽代碼

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
David Cermak 3 年之前
父節點
當前提交
bf8ceae780
共有 1 個文件被更改,包括 10 次插入2 次删除
  1. 10 2
      components/vfs/vfs.c

+ 10 - 2
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);