fix(storage/esp_libc): Fix poll return value discrepancy

This commit is contained in:
Tomáš Rohlínek
2026-01-14 08:28:05 +01:00
parent d66e59eae4
commit d7344e9658
2 changed files with 117 additions and 9 deletions
+100 -1
View File
@@ -1,14 +1,16 @@
/*
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <sys/param.h>
#include <sys/select.h>
#include <stdbool.h>
#include "unity.h"
#include "freertos/FreeRTOS.h"
#include "driver/uart.h"
@@ -37,6 +39,76 @@ typedef struct {
static const char message[] = "Hello world!";
typedef struct {
fd_set *readfds;
fd_set *writefds;
int local_fd;
bool ready_read;
bool ready_write;
} dummy_select_args_t;
static int dummy_open(const char *path, int flags, int mode)
{
return 0; // single local fd
}
static int dummy_close(int fd)
{
return 0;
}
static esp_err_t dummy_start_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, esp_vfs_select_sem_t sem, void **end_select_args)
{
(void) nfds;
(void) exceptfds;
dummy_select_args_t *args = calloc(1, sizeof(dummy_select_args_t));
if (args == NULL) {
return ESP_ERR_NO_MEM;
}
args->local_fd = 0;
args->readfds = readfds;
args->writefds = writefds;
args->ready_read = readfds && FD_ISSET(args->local_fd, readfds);
args->ready_write = writefds && FD_ISSET(args->local_fd, writefds);
if (!(args->ready_read || args->ready_write)) {
free(args);
*end_select_args = NULL;
return ESP_OK;
}
*end_select_args = args;
esp_vfs_select_triggered(sem);
return ESP_OK;
}
static esp_err_t dummy_end_select(void *end_select_args)
{
dummy_select_args_t *args = end_select_args;
if (!args) {
return ESP_OK;
}
if (args->ready_read && args->readfds) {
FD_SET(args->local_fd, args->readfds);
}
if (args->ready_write && args->writefds) {
FD_SET(args->local_fd, args->writefds);
}
free(args);
return ESP_OK;
}
static const esp_vfs_t dummy_vfs = {
.flags = ESP_VFS_FLAG_DEFAULT,
.open = dummy_open,
.close = dummy_close,
.start_select = dummy_start_select,
.end_select = dummy_end_select,
};
static int open_dummy_socket(void)
{
const struct addrinfo hints = {
@@ -526,6 +598,33 @@ TEST_CASE("UART can do poll() with POLLIN event", "[vfs]")
deinit(uart_fd, socket_fd);
}
TEST_CASE("poll() counts fd once when multiple events are set", "[vfs]")
{
ESP_ERROR_CHECK(esp_vfs_register("/dummy", &dummy_vfs, NULL));
const int fd = open("/dummy/test", O_RDONLY);
TEST_ASSERT_GREATER_OR_EQUAL(0, fd);
struct pollfd poll_fds[] = {
{
.fd = fd,
.events = POLLIN | POLLOUT,
},
{
.fd = -1,
},
};
int s = poll(poll_fds, sizeof(poll_fds)/sizeof(poll_fds[0]), 100);
TEST_ASSERT_EQUAL(1, s);
TEST_ASSERT_EQUAL(fd, poll_fds[0].fd);
TEST_ASSERT_EQUAL(POLLIN | POLLOUT, poll_fds[0].revents);
TEST_ASSERT_EQUAL(-1, poll_fds[1].fd);
TEST_ASSERT_EQUAL(0, poll_fds[1].revents);
close(fd);
ESP_ERROR_CHECK(esp_vfs_unregister("/dummy"));
}
TEST_CASE("UART can do poll() with POLLOUT event", "[vfs]")
{
int uart_fd;