Libc::dlsym() crashing on i686-linux-android


#1

The following code crashes with SIGFPE on x86 Android platform:

let name = "epoll_create1";
libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _);

Background: I was trying to use tokio-core on this platform and Core::new() kept crashing. Eventually I dug through mio and found that a call to dlsym() similar to the above was the culprit. Later I reproduced the crash independently using the above snippet without having to go through tokio-core or mio. This confirmed that the problem is specific to libc.

I know that i686-linux-android is officially UNsupported by libc. Still just out of curiosity why would code like the above fail and why would it fail with a floating point error? Any ideas?


#2

Shouldnt there be a null byte at the end of the string?

let name = "epoll_create1\0";
libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _);

#3

Well spotted @bjorn3 ! Yes, I missed the null terminator there. I just retried with the null terminator added and this code snippet did not crash.

So this rules out an issue in libc, which means the problem is in mio instead. The exact line where it’s crashing inside mio is this and the call stack in my case looks like this:

mio::Poll::new() -> Selector::new() -> Dlsym::get() -> ::fetch() -> libc::dlsym()

I tried with a local build of mio on my machine after changing the code inside fetch() to call dlsym() with a hardcoded value of "epoll_create1\0" and it still crashed!. I was hoping it won’t because I did put a null terminator in the hard-coded value. I need to go away and have another think about it.

As for the SIGFPE, I suppose it’s pointless to try to investigate why that is the specific error occurring. Once you got a memory overrun all bets oughta be off.


#4

https://issuetracker.google.com/issues/36982567

Seems like there’s at least 1 bug report of dlsym causing a sigfpe, but that bug report is fairly old. What android version are you using?


#5

Ok. Finally, what I’ve found is that the following statement:

libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _);

will crash on i686-linux-android regardless of whether it is called from mio or from any other code as long as name refers to a non-existent symbol – even when you have not forgotten the null terminator. My earlier statement that it works after adding the terminator to the string “epoll_create1” was misleading. I had not tried with "epoll_create1\0" but with "malloc\0" (Yeah, I’m having a bad-scientific-method-day today). It worked with "malloc\0" but still failed with "epoll_create1\0". Then I tried with "malloc1\0", and it failed. Which lead me to believe that it’s crashing with symbols that don’t exist and also that “epoll_create1” is a non-existent symbol on this platform.

In fact the code in mio is conscious about the likely absence of this symbol and is actively trying to guard against it. This is the code in question inside Selector::new()

        // Emulate `epoll_create` by using `epoll_create1` if it's available
        // and otherwise falling back to `epoll_create` followed by a call to
        // set the CLOEXEC flag.
        dlsym!(fn epoll_create1(c_int) -> c_int);

        match epoll_create1.get() {
            Some(epoll_create1_fn) => {
                cvt(epoll_create1_fn(libc::EPOLL_CLOEXEC))?
            }
            None => {
                let fd = cvt(libc::epoll_create(1024))?;
                drop(set_cloexec(fd));
                fd
            }
        }

Unfortunately for this code, instead of returning some result and making the fall-back to “epoll_create” work, epoll_create1.get() just crashes immediately.

In summary: The issue basically is that if you call libc::dlsym() on i686-linux-android for a symbol that does not exist it will crash right away instead of returning an error result. Also, the problem is inside libc not mio or tokio-core.


#6

The version of the emulator I’m using is KitKat 4.4 API level 19 (I’m new to Android programming so don’t know if that’s a complete version description).


#7

I’m not too familiar with Android development either. I’d suggest filing a bug report against that emulator and see what the maintainers say.


#8

Makes sense. I’ll try the same code on a different emulator first (the one I’m using right now is MS’s emulator)

Thanks for the help guys.