]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/posix-poll: Fix poll on files w/o epoll support
authorAndrei Tatar <andrei@unikraft.io>
Thu, 11 Jan 2024 14:31:44 +0000 (15:31 +0100)
committerUnikraft Bot <monkey@unikraft.io>
Tue, 6 Feb 2024 17:19:24 +0000 (17:19 +0000)
Previously calling poll() on a file not supporting epoll would propagate
the -EPERM error from epoll(); this is contrary to behavior on Linux,
where poll immediately returns with POLLIN|POLLOUT masked with the
requested events.
This change fixes this behavior, correctly handling unpollable files.

Checkpatch-Ignore: ENOSYS
Signed-off-by: Andrei Tatar <andrei@unikraft.io>
Reviewed-by: Ioan-Teodor Teugea <ioan_teodor.teugea@stud.acs.upb.ro>
Reviewed-by: Mihnea Firoiu <mihneafiroiu0@gmail.com>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
GitHub-Closes: #1258

lib/posix-poll/poll.c

index c67b554f97da69838f21770f6069fd924b3ca019..a98b805ef221a2366bab842c60ecf5c469a119d7 100644 (file)
@@ -71,22 +71,28 @@ int uk_sys_ppoll(struct pollfd *fds, nfds_t nfds,
                        r = uk_sys_epoll_ctl(ef, EPOLL_CTL_ADD, p->fd, &ev);
                        monitored++;
                }
-               if (unlikely(r))
-                       switch (r) {
-                       case -EBADF:
-                               p->revents = POLLNVAL;
-                               ret++;
-                               break;
-                       case -EEXIST:
-                               uk_pr_warn("Duplicate fd in poll: %d\n", p->fd);
-                               ret = -ENOSYS;
-                               goto out;
-                       default:
-                               ret = r;
-                               goto out;
-                       }
-               else
+               switch (r) {
+               case 0:
                        p->revents = 0;
+                       break;
+               case -EBADF:
+                       p->revents = POLLNVAL;
+                       ret++;
+                       break;
+               case -EPERM:
+                       /* Files without epoll support always return in|out */
+                       p->revents = (POLLIN|POLLOUT) & p->events;
+                       if (p->revents)
+                               ret++;
+                       break;
+               case -EEXIST:
+                       uk_pr_warn("Duplicate fd in poll: %d\n", p->fd);
+                       ret = -ENOSYS;
+                       goto out;
+               default:
+                       ret = r;
+                       goto out;
+               }
        }
        if (!monitored)
                monitored = 1; /* Need at least 1 return entry */