Skip to content

Commit d4ad311

Browse files
Gary-HobsonGUIDINGLI
authored andcommitted
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>
1 parent 114f2f1 commit d4ad311

File tree

1 file changed

+70
-79
lines changed

1 file changed

+70
-79
lines changed

fs/vfs/fs_poll.c

Lines changed: 70 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,48 @@ struct pollfd_s
5656
* Private Functions
5757
****************************************************************************/
5858

59+
/****************************************************************************
60+
* Name: poll_teardown
61+
*
62+
* Description:
63+
* Teardown the poll operation for each descriptor in the list and return
64+
* the count of non-zero poll events.
65+
*
66+
****************************************************************************/
67+
68+
static inline void poll_teardown(FAR struct pollfd *fds, nfds_t nfds,
69+
FAR int *count)
70+
{
71+
unsigned int i;
72+
73+
/* Process each descriptor in the list */
74+
75+
*count = 0;
76+
for (i = 0; i < nfds; i++)
77+
{
78+
if (fds[i].fd >= 0)
79+
{
80+
int status = poll_fdsetup(fds[i].fd, &fds[i], false);
81+
if (status < 0)
82+
{
83+
fds[i].revents |= POLLERR;
84+
}
85+
}
86+
87+
/* Check if any events were posted */
88+
89+
if (fds[i].revents != 0)
90+
{
91+
(*count)++;
92+
}
93+
94+
/* Un-initialize the poll structure */
95+
96+
fds[i].arg = NULL;
97+
fds[i].cb = NULL;
98+
}
99+
}
100+
59101
/****************************************************************************
60102
* Name: poll_setup
61103
*
@@ -68,8 +110,8 @@ static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds,
68110
FAR sem_t *sem)
69111
{
70112
unsigned int i;
71-
unsigned int j;
72113
int ret = OK;
114+
int count = 0;
73115

74116
/* Process each descriptor in the list */
75117

@@ -101,76 +143,31 @@ static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds,
101143
if (fds[i].fd >= 0)
102144
{
103145
ret = poll_fdsetup(fds[i].fd, &fds[i], true);
104-
}
105-
106-
if (ret < 0)
107-
{
108-
/* Setup failed for fds[i]. We now need to teardown previously
109-
* setup fds[0 .. (i - 1)] to release allocated resources and
110-
* to prevent memory corruption by access to freed/released 'fds'
111-
* and 'sem'.
112-
*/
113-
114-
for (j = 0; j < i; j++)
146+
if (ret < 0)
115147
{
116-
poll_fdsetup(fds[j].fd, &fds[j], false);
148+
poll_teardown(fds, i, &count);
149+
fds[i].revents |= POLLERR;
150+
fds[i].arg = NULL;
151+
fds[i].cb = NULL;
152+
return count + 1;
153+
}
154+
else if (fds[i].revents != 0)
155+
{
156+
count++;
117157
}
118-
119-
/* Indicate an error on the file descriptor */
120-
121-
fds[i].revents |= POLLERR;
122-
return ret;
123158
}
124159
}
125160

126-
return OK;
127-
}
128-
129-
/****************************************************************************
130-
* Name: poll_teardown
131-
*
132-
* Description:
133-
* Teardown the poll operation for each descriptor in the list and return
134-
* the count of non-zero poll events.
135-
*
136-
****************************************************************************/
137-
138-
static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds,
139-
FAR int *count)
140-
{
141-
unsigned int i;
142-
int status = OK;
143-
int ret = OK;
144-
145-
/* Process each descriptor in the list */
146-
147-
*count = 0;
148-
for (i = 0; i < nfds; i++)
161+
if (count > 0)
149162
{
150-
if (fds[i].fd >= 0)
151-
{
152-
status = poll_fdsetup(fds[i].fd, &fds[i], false);
153-
}
154-
155-
if (status < 0)
156-
{
157-
ret = status;
158-
}
159-
160-
/* Check if any events were posted */
161-
162-
if (fds[i].revents != 0)
163-
{
164-
(*count)++;
165-
}
166-
167-
/* Un-initialize the poll structure */
163+
/* If there are already events available in poll_setup,
164+
* we execute teardown and return immediately.
165+
*/
168166

169-
fds[i].arg = NULL;
170-
fds[i].cb = NULL;
167+
poll_teardown(fds, i, &count);
171168
}
172169

173-
return ret;
170+
return count;
174171
}
175172

176173
/****************************************************************************
@@ -425,8 +422,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
425422
FAR struct pollfd *kfds;
426423
sem_t sem;
427424
int count = 0;
428-
int ret2;
429-
int ret;
425+
int ret = OK;
430426

431427
DEBUGASSERT(nfds == 0 || fds != NULL);
432428

@@ -458,8 +454,13 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
458454
/* Set up the poll structure */
459455

460456
nxsem_init(&sem, 0, 0);
461-
ret = poll_setup(kfds, nfds, &sem);
462-
if (ret >= 0)
457+
458+
/* If there are already events available in poll_setup,
459+
* we return immediately
460+
*/
461+
462+
count = poll_setup(kfds, nfds, &sem);
463+
if (count == 0)
463464
{
464465
struct pollfd_s fdsinfo;
465466

@@ -471,13 +472,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
471472
fdsinfo.nfds = nfds;
472473
tls_cleanup_push(tls_get_info(), poll_cleanup, &fdsinfo);
473474

474-
if (timeout == 0)
475-
{
476-
/* Poll returns immediately whether we have a poll event or not. */
477-
478-
ret = OK;
479-
}
480-
else if (timeout > 0)
475+
if (timeout > 0)
481476
{
482477
/* "Implementations may place limitations on the granularity of
483478
* timeout intervals. If the requested timeout interval requires
@@ -509,7 +504,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
509504
/* EINTR is the only other error expected in normal operation */
510505
}
511506
}
512-
else
507+
else if (timeout < 0)
513508
{
514509
/* Wait for the poll event or signal with no timeout */
515510

@@ -522,11 +517,7 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
522517
* Preserve ret, if negative, since it holds the result of the wait.
523518
*/
524519

525-
ret2 = poll_teardown(kfds, nfds, &count);
526-
if (ret2 < 0 && ret >= 0)
527-
{
528-
ret = ret2;
529-
}
520+
poll_teardown(kfds, nfds, &count);
530521

531522
/* Pop the cancellation point */
532523

0 commit comments

Comments
 (0)