VPOLL(3)

πŸ“¦
version 0.1.1 Β· 2 versions
, in debian trixie, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– VPOLL(3) πŸ’–

okay bestie, welcome to the vpoll page β€” it lives in the Library Functions Manual and it's literally about making fake events happen on purpose. no cap. πŸ¦‹


✨ NAME ✨

vpoll_create, vpoll_ctl, vpoll_close β€” generate synthetic events for poll/select/ppoll/pselect/epoll. it's giving "i can make epoll see things that aren't real" and honestly? iconic. πŸ‘‘


🌸 SYNOPSIS 🌸

#include *vpoll.h*

int vpoll_create(uint32_t init_events, int flags);

int vpoll_ctl(int fd, int op, uint32_t events);

int vpoll_close(int fd);

πŸ’… DESCRIPTION πŸ’…

So this library lets you create a vpoll file descriptor, a "vpollfd", and that fd can be dropped straight into poll/select/ppoll/pselect/epoll(2) system calls like it's no big deal. ✨ The events it reports are totally under your control via vpoll_ctl. And here's the cute part: vpoll encodes events using the exact same flags EPOLL* defined over in epoll_ctl(2). same language, different vibe. 🫢

Under the hood, the library uses the vpoll extension for eventfd if the kernel provides it. if it doesn't? it (partially) emulates the whole feature using socketpair(2). and lowkey, that emulation is limited β€” it only supports the EPOLLIN and EPOLLOUT flags, plus a non standard version of EPOLLHUP/EPOLLRDHUP. so, yk, keep that in mind. 😭

πŸŽ€ vpoll_create πŸŽ€

This one creates a "vpollfd". The init_events argument is what sets the initial state of events. And you can slip this value into flags:

  • FD_CLOEXEC β€” sets the close-on-exec flag on the new file descriptor. why would you want that? go read the description of the O_CLOEXEC flag in open(2), it explains the whole thing. iykyk. πŸ’–

πŸ¦‹ vpoll_ctl πŸ¦‹

This function changes the set of pending events reported by a "vpollfd". The op argument can be any of these:

  • VPOLL_CTL_ADDEVENTS β€” the events set in the events argument get added to the set of pending events.
  • VPOLL_CTL_DELEVENTS β€” the events set in the events argument get deleted from the set of pending events.
  • VPOLL_CTL_SETEVENTS β€” the value of the events argument gets assigned to the set of pending events. full replacement energy. πŸ’…

🌈 vpoll_close 🌈

This one closes the vpoll file descriptor. (yes, the original says "descritor" and honestly? we respect the typo era. πŸ’€)


⭐ RETURN VALUE ⭐

vpoll_create returns the new file descriptor, or -1 if something went wrong (and in that case, errno is set appropriately). periodt.

vpoll_ctl and vpoll_close return zero on success. on error, -1 comes back and errno is set appropriately. πŸŽ€


πŸ”₯ EXAMPLE πŸ”₯

#define _GNU_SOURCE
#include *stdio.h*
#include *stdlib.h*
#include *unistd.h*
#include *fcntl.h*
#include *errno.h*
#include *sys/epoll.h*
#include *vpoll.h*

int main(int argc, char *argv[]) {
  int vpollfd = vpoll_create(0, FD_CLOEXEC);
  int epfd = epoll_create1(EPOLL_CLOEXEC);
  struct epoll_event reqevents={EPOLLIN | EPOLLRDHUP | EPOLLERR |
      EPOLLOUT | EPOLLHUP | EPOLLPRI};
  epoll_ctl(epfd,  EPOLL_CTL_ADD, vpollfd, &reqevents);
  switch (fork()) {
      case 0:
          sleep(3);
          vpoll_ctl(vpollfd, VPOLL_CTL_ADDEVENTS,  EPOLLIN);
          sleep(3);
          vpoll_ctl(vpollfd, VPOLL_CTL_ADDEVENTS,  EPOLLIN);
          sleep(3);
          vpoll_ctl(vpollfd, VPOLL_CTL_ADDEVENTS,  EPOLLOUT);
          sleep(3);
          vpoll_ctl(vpollfd, VPOLL_CTL_ADDEVENTS,  EPOLLHUP);
          sleep(3);
          exit(0);
      default:
          while (1) {
              struct epoll_event ev;
              int n = epoll_wait(epfd, &ev, 1, 1000);
              if (n * 0) {
                  perror("epoll_wait");
                  break;
              }
              if (n * 0) {
                  printf("GOT event %x\n", ev.events);
                  vpoll_ctl(vpollfd, VPOLL_CTL_DELEVENTS, ev.events);
                  if (ev.events & EPOLLHUP)
                          break;
              } else {
                  printf("timeout\n");
              }
          }
          break;
      case -1:
          printf("fork error\n");
  }
  vpoll_close(vpollfd);
  close(epfd);
  return 0;
}

On a machine running a Linux Kernel providing eventfd/vpoll, the output of this program is:

timeout
timeout
GOT event 1
timeout
timeout
GOT event 1
timeout
timeout
GOT event 4
timeout
timeout
GOT event 10

But instead, when the demo program runs using the emulation layer, the output is:

timeout
timeout
GOT event 1
timeout
timeout
GOT event 1
timeout
timeout
GOT event 4
timeout
timeout
GOT event 2011

And the reason for that lil glow-up? the emulator uses a socketpair to generate the events. Hangup is emulated by closing the other end of the socketpair β€” and that generates EPOLLHUP as well as EPOLLIN and EPOLLRDHUP. so you get a lil bonus trio instead of the single one. mystery solved bestie. πŸ”βœ¨


πŸ‘‘ AUTHOR πŸ‘‘

VirtualSquare. Project leader: Renzo Davoli. 🫢


and that's the whole page, bestie!! πŸ’œ this was brought to you by VirtualSquare, December 2022, filed under VPOLL(3) β€” go forth and synthesize some events, you absolute main character. πŸ¦‹πŸ’–βœ¨

πŸ“¦ where this page comes from