fs: Set the poll return value according to the man manual
The man manual describes that poll only has EFAULT, EINTR, EINVAL, and ENOMEM return values. If a file returns an error, the POLLERR event should be set and OK should be returned https://man7.org/linux/man-pages/man2/poll.2.html When using libuv to poll the socket, the socket poll returned an EBUSY error, causing libuv to abort. The expected logic should be to return OK, allowing libuv to notify the event listener that the POLLERR event occurred. Signed-off-by: yinshengkai <yinshengkai@xiaomi.com> Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
parent
36ddb46dba
commit
e4e355d164
1 changed files with 70 additions and 79 deletions
153
fs/vfs/fs_poll.c
153
fs/vfs/fs_poll.c
|
@ -56,6 +56,48 @@ struct pollfd_s
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: poll_teardown
|
||||
*
|
||||
* Description:
|
||||
* Teardown the poll operation for each descriptor in the list and return
|
||||
* the count of non-zero poll events.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void poll_teardown(FAR struct pollfd *fds, nfds_t nfds,
|
||||
FAR int *count)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Process each descriptor in the list */
|
||||
|
||||
*count = 0;
|
||||
for (i = 0; i < nfds; i++)
|
||||
{
|
||||
if (fds[i].fd >= 0)
|
||||
{
|
||||
int status = poll_fdsetup(fds[i].fd, &fds[i], false);
|
||||
if (status < 0)
|
||||
{
|
||||
fds[i].revents |= POLLERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if any events were posted */
|
||||
|
||||
if (fds[i].revents != 0)
|
||||
{
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
/* Un-initialize the poll structure */
|
||||
|
||||
fds[i].arg = NULL;
|
||||
fds[i].cb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: poll_setup
|
||||
*
|
||||
|
@ -68,8 +110,8 @@ static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds,
|
|||
FAR sem_t *sem)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
int ret = OK;
|
||||
int count = 0;
|
||||
|
||||
/* Process each descriptor in the list */
|
||||
|
||||
|
@ -101,76 +143,31 @@ static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds,
|
|||
if (fds[i].fd >= 0)
|
||||
{
|
||||
ret = poll_fdsetup(fds[i].fd, &fds[i], true);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Setup failed for fds[i]. We now need to teardown previously
|
||||
* setup fds[0 .. (i - 1)] to release allocated resources and
|
||||
* to prevent memory corruption by access to freed/released 'fds'
|
||||
* and 'sem'.
|
||||
*/
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
poll_fdsetup(fds[j].fd, &fds[j], false);
|
||||
}
|
||||
|
||||
/* Indicate an error on the file descriptor */
|
||||
|
||||
poll_teardown(fds, i, &count);
|
||||
fds[i].revents |= POLLERR;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: poll_teardown
|
||||
*
|
||||
* Description:
|
||||
* Teardown the poll operation for each descriptor in the list and return
|
||||
* the count of non-zero poll events.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds,
|
||||
FAR int *count)
|
||||
{
|
||||
unsigned int i;
|
||||
int status = OK;
|
||||
int ret = OK;
|
||||
|
||||
/* Process each descriptor in the list */
|
||||
|
||||
*count = 0;
|
||||
for (i = 0; i < nfds; i++)
|
||||
{
|
||||
if (fds[i].fd >= 0)
|
||||
{
|
||||
status = poll_fdsetup(fds[i].fd, &fds[i], false);
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
ret = status;
|
||||
}
|
||||
|
||||
/* Check if any events were posted */
|
||||
|
||||
if (fds[i].revents != 0)
|
||||
{
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
/* Un-initialize the poll structure */
|
||||
|
||||
fds[i].arg = NULL;
|
||||
fds[i].cb = NULL;
|
||||
return count + 1;
|
||||
}
|
||||
else if (fds[i].revents != 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (count > 0)
|
||||
{
|
||||
/* If there are already events available in poll_setup,
|
||||
* we execute teardown and return immediately.
|
||||
*/
|
||||
|
||||
poll_teardown(fds, i, &count);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -425,8 +422,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
|
|||
FAR struct pollfd *kfds;
|
||||
sem_t sem;
|
||||
int count = 0;
|
||||
int ret2;
|
||||
int ret;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(nfds == 0 || fds != NULL);
|
||||
|
||||
|
@ -458,8 +454,13 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
|
|||
/* Set up the poll structure */
|
||||
|
||||
nxsem_init(&sem, 0, 0);
|
||||
ret = poll_setup(kfds, nfds, &sem);
|
||||
if (ret >= 0)
|
||||
|
||||
/* If there are already events available in poll_setup,
|
||||
* we return immediately
|
||||
*/
|
||||
|
||||
count = poll_setup(kfds, nfds, &sem);
|
||||
if (count == 0)
|
||||
{
|
||||
struct pollfd_s fdsinfo;
|
||||
|
||||
|
@ -471,13 +472,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
|
|||
fdsinfo.nfds = nfds;
|
||||
tls_cleanup_push(tls_get_info(), poll_cleanup, &fdsinfo);
|
||||
|
||||
if (timeout == 0)
|
||||
{
|
||||
/* Poll returns immediately whether we have a poll event or not. */
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
else if (timeout > 0)
|
||||
if (timeout > 0)
|
||||
{
|
||||
/* "Implementations may place limitations on the granularity of
|
||||
* timeout intervals. If the requested timeout interval requires
|
||||
|
@ -509,7 +504,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
|
|||
/* EINTR is the only other error expected in normal operation */
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (timeout < 0)
|
||||
{
|
||||
/* Wait for the poll event or signal with no timeout */
|
||||
|
||||
|
@ -522,11 +517,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
|
|||
* Preserve ret, if negative, since it holds the result of the wait.
|
||||
*/
|
||||
|
||||
ret2 = poll_teardown(kfds, nfds, &count);
|
||||
if (ret2 < 0 && ret >= 0)
|
||||
{
|
||||
ret = ret2;
|
||||
}
|
||||
poll_teardown(kfds, nfds, &count);
|
||||
|
||||
/* Pop the cancellation point */
|
||||
|
||||
|
|
Loading…
Reference in a new issue