]> granicus.if.org Git - esp-idf/commitdiff
VFS select: Correct reseting of socket FDs
authorRoland Dobai <dobai.roland@gmail.com>
Thu, 24 May 2018 08:02:24 +0000 (10:02 +0200)
committerbot <bot@espressif.com>
Fri, 25 May 2018 13:37:43 +0000 (13:37 +0000)
When using multiple sockets, some of them could be incorrectly removed
from the fd_sets before passing these fd_sets forward to the socket
select function.

Closes https://github.com/espressif/esp-idf/issues/1987

components/vfs/test/test_vfs_select.c
components/vfs/vfs.c

index 5febf39a475b579918407979d63e8bb3ac62fce3..be74ebe910173f96bef728a5e4716fa388ea4188 100644 (file)
@@ -33,6 +33,24 @@ typedef struct {
 
 static const char message[] = "Hello world!";
 
+static int open_dummy_socket()
+{
+    const struct addrinfo hints = {
+        .ai_family = AF_INET,
+        .ai_socktype = SOCK_DGRAM,
+    };
+    struct addrinfo *res = NULL;
+
+    const int err = getaddrinfo("localhost", "80", &hints, &res);
+    TEST_ASSERT_EQUAL(0, err);
+    TEST_ASSERT_NOT_NULL(res);
+
+    const int dummy_socket_fd = socket(res->ai_family, res->ai_socktype, 0);
+    TEST_ASSERT(dummy_socket_fd >= 0);
+
+    return dummy_socket_fd;
+}
+
 static int socket_init()
 {
     const struct addrinfo hints = {
@@ -185,11 +203,13 @@ TEST_CASE("socket can do select()", "[vfs]")
     char recv_message[sizeof(message)];
 
     init(&uart_fd, &socket_fd);
+    const int dummy_socket_fd = open_dummy_socket();
 
     fd_set rfds;
     FD_ZERO(&rfds);
     FD_SET(uart_fd, &rfds);
     FD_SET(socket_fd, &rfds);
+    FD_SET(dummy_socket_fd, &rfds);
 
     const test_task_param_t test_task_param = {
         .fd = socket_fd,
@@ -199,9 +219,10 @@ TEST_CASE("socket can do select()", "[vfs]")
     TEST_ASSERT_NOT_NULL(test_task_param.sem);
     start_task(&test_task_param);
 
-    const int s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv);
-    TEST_ASSERT_EQUAL(s, 1);
+    const int s = select(MAX(MAX(uart_fd, socket_fd), dummy_socket_fd) + 1, &rfds, NULL, NULL, &tv);
+    TEST_ASSERT_EQUAL(1, s);
     TEST_ASSERT_UNLESS(FD_ISSET(uart_fd, &rfds));
+    TEST_ASSERT_UNLESS(FD_ISSET(dummy_socket_fd, &rfds));
     TEST_ASSERT(FD_ISSET(socket_fd, &rfds));
 
     int read_bytes = read(socket_fd, recv_message, sizeof(message));
@@ -212,6 +233,7 @@ TEST_CASE("socket can do select()", "[vfs]")
     vSemaphoreDelete(test_task_param.sem);
 
     deinit(uart_fd, socket_fd);
+    close(dummy_socket_fd);
 }
 
 TEST_CASE("select() timeout", "[vfs]")
index 36944ddda5af7013f32342c6bda1f615f014cf25..a5f3c74c7dfcba748fd95565e75ec5117a570e07 100644 (file)
@@ -782,13 +782,15 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds
             continue;
         }
 
-        if (!socket_select && is_socket_fd) {
-            // no socket_select found yet and the fd is for a socket so take a look
-            if ((readfds && FD_ISSET(fd, readfds)) ||
-                    (writefds && FD_ISSET(fd, writefds)) ||
-                    (errorfds && FD_ISSET(fd, errorfds))) {
-                const vfs_entry_t *vfs = s_vfs[vfs_index];
-                socket_select = vfs->vfs.socket_select;
+        if (is_socket_fd) {
+            if (!socket_select) {
+                // no socket_select found yet so take a look
+                if ((readfds && FD_ISSET(fd, readfds)) ||
+                        (writefds && FD_ISSET(fd, writefds)) ||
+                        (errorfds && FD_ISSET(fd, errorfds))) {
+                    const vfs_entry_t *vfs = s_vfs[vfs_index];
+                    socket_select = vfs->vfs.socket_select;
+                }
             }
             continue;
         }