diff --git a/components/lwip/port/esp32/vfs_lwip.c b/components/lwip/port/esp32/vfs_lwip.c index 54d71912bb..c795fbe800 100644 --- a/components/lwip/port/esp32/vfs_lwip.c +++ b/components/lwip/port/esp32/vfs_lwip.c @@ -40,6 +40,14 @@ static void lwip_stop_socket_select_isr(BaseType_t *woken) } } +static void *lwip_get_socket_select_semaphore() +{ + /* Calling this from the same process as select() will ensure that the semaphore won't be allocated from + * ISR (lwip_stop_socket_select_isr). + */ + return (void *) sys_thread_sem_get(); +} + static int lwip_fcntl_r_wrapper(int fd, int cmd, va_list args) { return lwip_fcntl_r(fd, cmd, va_arg(args, int)); @@ -61,6 +69,7 @@ void esp_vfs_lwip_sockets_register() .read = &lwip_read_r, .fcntl = &lwip_fcntl_r_wrapper, .ioctl = &lwip_ioctl_r_wrapper, + .get_socket_select_semaphore = &lwip_get_socket_select_semaphore, .socket_select = &lwip_select, .stop_socket_select = &lwip_stop_socket_select, .stop_socket_select_isr = &lwip_stop_socket_select_isr, diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index 57a0320f18..7033b26765 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -221,6 +221,8 @@ typedef struct /** stop_socket_select which can be called from ISR; set only for the socket driver */ void (*stop_socket_select_isr)(BaseType_t *woken); /** end_select is called to stop the I/O multiplexing and deinitialize the environment created by start_select for the given VFS */ + void* (*get_socket_select_semaphore)(); + /** get_socket_select_semaphore returns semaphore allocated in the socket driver; set only for the socket driver */ void (*end_select)(); } esp_vfs_t; diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index a1ed31fbd2..1936cfc87e 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -838,6 +838,16 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds esp_vfs_safe_fd_isset(fd, errorfds)) { const vfs_entry_t *vfs = s_vfs[vfs_index]; socket_select = vfs->vfs.socket_select; + + // get_socket_select_semaphore needs to be set for a socket driver where semaphore can be + // initialized outside interrupt handlers (ignoring this could result in unexpected failures) + if (vfs->vfs.get_socket_select_semaphore != NULL) { + vfs->vfs.get_socket_select_semaphore(); // Semaphore is returned and it was allocated if it + // wasn't before. We don't use the return value just need to be sure that it doesn't get + // allocated later from ISR. + // Note: ESP-IDF v4.0 will start to use this callback differently with some breaking changes + // in the VFS API. + } } } continue;