mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(storage/esp_libc): Fix poll return value discrepancy
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -22,7 +22,6 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
|||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
fd_set writefds;
|
fd_set writefds;
|
||||||
fd_set errorfds;
|
fd_set errorfds;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (fds == NULL) {
|
if (fds == NULL) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
@@ -43,7 +42,6 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
|||||||
|
|
||||||
if (fds[i].fd >= FD_SETSIZE) {
|
if (fds[i].fd >= FD_SETSIZE) {
|
||||||
fds[i].revents |= POLLNVAL;
|
fds[i].revents |= POLLNVAL;
|
||||||
++ret;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,10 +60,17 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
|||||||
|
|
||||||
const int select_ret = select(max_fd + 1, &readfds, &writefds, &errorfds, timeout < 0 ? NULL : &tv);
|
const int select_ret = select(max_fd + 1, &readfds, &writefds, &errorfds, timeout < 0 ? NULL : &tv);
|
||||||
|
|
||||||
if (select_ret > 0) {
|
if (select_ret < 0) {
|
||||||
ret += select_ret;
|
// keeping the errno from select()
|
||||||
|
return select_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select_ret > 0) {
|
||||||
for (unsigned int i = 0; i < nfds; ++i) {
|
for (unsigned int i = 0; i < nfds; ++i) {
|
||||||
|
if (fds[i].fd < 0 || fds[i].fd >= FD_SETSIZE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (FD_ISSET(fds[i].fd, &readfds)) {
|
if (FD_ISSET(fds[i].fd, &readfds)) {
|
||||||
fds[i].revents |= POLLIN;
|
fds[i].revents |= POLLIN;
|
||||||
}
|
}
|
||||||
@@ -78,9 +83,13 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
|||||||
fds[i].revents |= POLLERR;
|
fds[i].revents |= POLLERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
ret = select_ret;
|
|
||||||
// keeping the errno from select()
|
int ret = 0;
|
||||||
|
for (unsigned int i = 0; i < nfds; ++i) {
|
||||||
|
if (fds[i].revents != 0) {
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
@@ -37,6 +39,76 @@ typedef struct {
|
|||||||
|
|
||||||
static const char message[] = "Hello world!";
|
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)
|
static int open_dummy_socket(void)
|
||||||
{
|
{
|
||||||
const struct addrinfo hints = {
|
const struct addrinfo hints = {
|
||||||
@@ -526,6 +598,33 @@ TEST_CASE("UART can do poll() with POLLIN event", "[vfs]")
|
|||||||
deinit(uart_fd, socket_fd);
|
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]")
|
TEST_CASE("UART can do poll() with POLLOUT event", "[vfs]")
|
||||||
{
|
{
|
||||||
int uart_fd;
|
int uart_fd;
|
||||||
|
|||||||
Reference in New Issue
Block a user