Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EPOLL_CTL_ADD used when trying to modify a file descriptor #29

Closed
weissi opened this issue Dec 7, 2016 · 7 comments
Closed

EPOLL_CTL_ADD used when trying to modify a file descriptor #29

weissi opened this issue Dec 7, 2016 · 7 comments

Comments

@weissi
Copy link

weissi commented Dec 7, 2016

basically if a file descriptor is first only used for reading (EPOLLIN) and later on switches to reading and writing (EPOLLOUT), there's currently no way to modify the epoll set as EPOLL_CTL_ADD is used unconditionally (but it should be EPOLL_CTL_MOD). Full details here: https://bugs.swift.org/browse/SR-3360

@LubosD
Copy link

LubosD commented Mar 1, 2017

Also encountered under Darling macOS emulation. The problem is the descriptor is added into 2 different filters and libkqueue has no idea the fd has already been added into epoll.

@LubosD
Copy link

LubosD commented Mar 1, 2017

This is my solution: darlinghq@67c22f9

The idea is to dup() every fd before adding it into epoll, since otherwise we cannot have the same fd in epoll twice with possibly different flags (oneshot and/or edge triggered).

If the application using kqueue expects fds to be automatically removed from kqueue when closed, more hacks will be required to mimick the behavior.

@arr2036
Copy link
Collaborator

arr2036 commented Mar 25, 2019

This surprises me as there should be one epoll instance per kqueue/filter. Could you provide some example code to reproduce the issue?

@LubosD
Copy link

LubosD commented Mar 25, 2019

filter_epfd() gets the epoll file descriptor from the kqueue object, so there is just one such instance.

@arr2036
Copy link
Collaborator

arr2036 commented Mar 25, 2019

Ugh, you're right. OK, well I guess we should maintain separate epoll instances for each filter. I don't think there's really an issue with that other than we burn an extra fd per kqueue.

@ghost
Copy link

ghost commented Sep 3, 2019

I tried using libkqueue as an alternative to buying an overpriced Apple computer only to have the kqueue API. libkqueue does not work for my application as, just like pointed out here, EV_ADD translates to EPOLL_CTL_ADD and not (EPOLL_CTL_ADD/EPOLL_CTL_MOD). This makes it basically impossible to implement the most basic network application as the flow goes like this:

  • creating a socket gives you an FD
  • connect using said FD gives you EINPROGRESS
  • start polling for writable on that FD (adds the FD to epoll)
  • when writable, modify it to poll for readable (fails with EEXIST since libkqueue already added the FD)
  • now the app is broken

@bombwork
Copy link

Kqueue isn't osx exclusive feature.

Kqueue is a scalable event notification interface introduced in FreeBSD 4.1 on July 2000,[1][2] also supported in NetBSD, OpenBSD, DragonFly BSD, and macOS.

Additionally FreeBSD allows to crosscompile apps for osx

ghostmansd pushed a commit to ghostmansd/libkqueue that referenced this issue Apr 28, 2021
…o avoid conflicts between EVFILT_READ and EVFILT_WRITE Closes mheily#29 Closes mheily#59

There's more work required, but at least this fixes the outstanding issues.

Known limitations:
- Need to verify correct behaviour of EV_DISPATCH when both filters are registered for events.  This now needs to be implemented internally by libkqueue instead of relying on EPOLLET, as EPOLLET applies to both EPOLLIN and EPOLLOUT.

- If the number of events we are to return does not have sufficient space for at least two entries when polling an FD registered for both read and write events, the write event will be lost.  We can fix this by implementing a linked list of pending events we return before calling the platform's wait function. Will probably copy the dlist implementation from FreeRADIUS across, as it's been well tested, and is a header only implementation like the current rbtree. A dlist is needed to store entries for EVFILT_PROC anyway, which is the next filter that needs major attention.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants