-
Notifications
You must be signed in to change notification settings - Fork 266
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
Undefined reference to syscalls in r15 #394
Comments
looks like a bug in libev: #ifdef EPOLL_CLOEXEC https://github.com/BeeswaxIO/libev/blob/a92e9ffa951d26a90212a2ff207dbfafd2790e1f/ev_epoll.c#L241 they assume that if the EPOLL_CLOEXEC constant is available, epoll_create1 is available. that's not true on Android. they need either a configure-style test for epoll_create1, or they can check ANDROID_API >= 21. they make the same incorrect assumption with inotify_init1: #if defined IN_CLOEXEC && defined IN_NONBLOCK |
@enh What? Why isn't that true on Android? And why did it work back in r14? |
Because there wasn't a C library wrapper for
r14 defaulted to using the deprecated, waaaaaaay out of date headers. r15 has made unified headers the default. |
Thanks for the explanation! Btw is
|
Yep, |
Thanks. Closing this. |
NDK r15 introduced unified headers which will cause libev failing to link. This commit checks Android API version before attempting to invoke new syscalls. More information: android/ndk#394 (comment)
NDK r15 introduced unified headers which will cause libev failing to link. This commit checks Android API version before attempting to invoke new syscalls. More information: android/ndk#394 (comment)
FWIW, this is a duplicate of #302 |
@DanAlbert , @enh what solution would you recommend?
For boost, we are currently using another ugly workaround (note there is still no activity on https://svn.boost.org/trac/boost/ticket/12863):
|
Boost already has fallback code if |
I was brought up on "detect features, not versions" so I am very unhappy with spreading |
well, we've all lived with the alternative in the NDK for years, so we know how well that works out :-) but in this case detecting the feature is the "try epoll_create1, fall back to epoll_create, fall back to poll/select" code. Android doesn't mandate kernel versions, so even with the legacy headers seeing EPOLL_CLOEXEC didn't mean much if anything. |
What about adding to
This will fix at least boost and libev in backwards-compatible way. |
Actually, I suppose we can do even better and just do: static __inline int epoll_create1(int flags) {
return syscall(__NR_epoll_create1, flags);
} right? We've talked about trying to get libc_syscalls.a into the NDK for this kind of thing already, and this is pretty much the same thing. |
The downside of that approach is that it turns a build failure into a run time failure if the calling code isn't tolerant of the fact that syscalls with functions might not actually be available in the kernel. Boost and libev both are, but I'm not sure how common that is. |
Seems like a good idea to me.
|
The major problem with |
😱 Do you know what they actually do instead of ENOSYS? Is it something like a device vendor using the next available syscall number instead of picking a number way out of range? |
we've certainly seen that happen numerous times, but there's not much we can do about it other than (a) always have CTS tests for any new syscall wrapper we add, and (b) longer term try to move to a world where we do mandate minimum kernel versions. in this specific case, epoll_create1 and inotify_init1 are so old that there aren't any devices still running with kernels that old. |
The question is which fallback is safer: to use My opinion is that the latter is safer, because we do know that libc does not export Please note that |
Also an issue in Asio (might be the same issue as Boost since Asio is now part of Boost) From a user (app developer) point of view if EPOLL_CLOEXEC exists then epoll_create1 should exist for consistency, or there should be a simple compile-time way to check for it (checking for specific Android versions in user code is horrible, we should check for features not versions). |
I think we need to do something about this before r15 goes to stable, but we're still talking this one over (been busy with I/O this week). Quick summary of our options:
I really don't like turning compile-time errors into run-time errors. Especially because in this case you could be running on a device where
The scary part about this is that, as @alexcohn pointed out, the device's kernel might have used that syscall number for an extension already, so this might end up calling some bogus syscall rather than the one you want (or returning @jmgao pointed out that we could just skip calling
While technically correct (the best kind of correct!), this isn't great. The number of people that have landed on bugs like this from just the beta is a pretty clear indication that we probably can't stand on the ground of "but that code is wrong". I'd really like to take this option, but I think it will be an uphill battle to convince so many third party projects that the availability of syscalls says nothing about the availability of C library wrappers and vice versa.
This choice actively restricts functionality. The existence of This might be the least bad choice in the short term. If nothing else, this is the solution which can change our minds on with the least impact (this might be a decision best left until we work out any other kinks in unified headers). This also preserves the behavior of the old headers, so at the very least this doesn't make anything worse. I was completely against 4 when I started writing this, but I think I've convinced myself that it's what we should do for r15 even if we don't stick with it for future releases. Thoughts? |
I still don't fully understand the risk of hiding EPOLL_CLOEXEC. People who are smart enough to use |
I suppose that's true. We all are pretty settled on option 4 for the time being anyway. Odds are we'll do that and no one will ever complain about this issue, so I'm overthinking something that no one actually cares about :) |
I doubt there's any actual risk, but from an puritanical standpoint, hiding EPOLL_CLOEXEC and not hiding __NR_epoll_create1 is the same sort of problem as showing EPOLL_CLOEXEC and not having epoll_create1, except even worse, since __NR_epoll_create1 and EPOLL_CLOEXEC actually are a logical unit that comes from the kernel. |
Some third-party code uses the existence of EPOLL_CLOEXEC to detect the availability of epoll_create1. This is not correct, since having up-to-date UAPI headers says nothing about the C library, but for the time being we don't want to harm adoption to the unified headers. We'll undef EPOLL_CLOEXEC if we don't have epoll_create1 for the time being, and maybe revisit this later. Test: make checkbuild Bug: android/ndk#302 Bug: android/ndk#394 Change-Id: I8ee9ce62768fb174070ec51d114f477389befc4a
Some third-party code uses the existence of IN_CLOEXEC/IN_NONBLOCK to detect the availability of inotify_init1. This is not correct, since `syscall(__NR_inotify_init1, IN_CLOEXEC)` is still valid even if the C library doesn't have that function, but for the time being we don't want to harm adoption to the unified headers. We'll avoid defining IN_CLOEXEC and IN_NONBLOCK if we don't have inotify_init1 for the time being, and maybe revisit this later. Test: make checkbuild Bug: android/ndk#394 Change-Id: Iefdc1662b21045de886c7ad1cbeba6241163d943
We did actually change the unified headers to not expose constants before the corresponding functions are available (at least in the epoll/inotify cases that caused trouble, plus sync_file_range which we spotted in passing). Bug: android/ndk#302 Bug: android/ndk#394 Test: N/A Change-Id: Ia46b56862475f68a8ae3fa3677532c828eec390c
…d instead use the older epoll_create See android/ndk#394 for more information
Description
Travis using r14 works: https://travis-ci.org/shadowsocks/shadowsocks-android/builds/232310650
Source code: https://github.com/shadowsocks/shadowsocks-android
Environment Details
The text was updated successfully, but these errors were encountered: