JellicleCat JellicleCat - 1 year ago 489
Android Question

Android linker: undefined reference to bsd_signal

I'm running

to compile an Android app that has a static lib dependency. Somehow, I have an undefined reference to

I was able to compile this app with gradle 1.X, but I've been obliged to switch to gradle 2.10 and to drop my
file in favour of putting more build instruction into my
file, and this is where the trouble arises.

Can anyone tell me whether there is a library that defines
, which I should link to my project?

Compiler output

Starting process 'command '/home/myself/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++''. Working directory: /home/myself/projects/DroidEar/app Command: /home/myself/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ @/home/myself/projects/DroidEar/app/build/tmp/linkNativeArmeabi-v7aDebugSharedLibrary/options.txt
Successfully started process 'command '/home/myself/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++''
/android/ndk/platforms/android-9/arch-arm/usr/include/signal.h:113: error: undefined reference to 'bsd_signal'
/android/ndk/platforms/android-9/arch-arm/usr/include/signal.h:113: error: undefined reference to 'bsd_signal'
collect2: error: ld returned 1 exit status

TMI: Here is my file

apply plugin: ''

model {
repositories {
libs(PrebuiltLibraries) {
Superpowered {
binaries.withType(StaticLibraryBinary) {
def prefix = "src/main/jniLibs/Superpowered"
headers.srcDir "${prefix}"
if (targetPlatform.getName() == "armeabi-v7a")
staticLibraryFile = file("${prefix}/libSuperpoweredAndroidARM.a")
else if (targetPlatform.getName() == "arm64-v8a")
staticLibraryFile = file("${prefix}/libSuperpoweredAndroidARM64.a")
else if (targetPlatform.getName() == "x86_64")
staticLibraryFile = file("${prefix}/libSuperpoweredAndroidX86_64.a")
else if (targetPlatform.getName() == "X86")
staticLibraryFile = file("${prefix}/libSuperpoweredAndroidX86.a")

android {
compileSdkVersion = 23
buildToolsVersion = "23.0.3"

sources {
main {
jni {
dependencies {
library "Superpowered" linkage "static"

ndk {
ldLibs.addAll(['log', 'android', 'c'])

defaultConfig {
applicationId = "edu.ucdavis.auditoryenhancer"
minSdkVersion.apiLevel = 22
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"

android.ndk {
moduleName = "native"

android.buildTypes {
release {
minifyEnabled = false

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'

It looks to me like
is defined in the
component of
, but even with my
call above including
, I get the error.

Answer Source

Till android-19 inclusive NDK-s signal.h declared bsd_signal extern and signal was an inline calling bsd_signal

Starting with android-21 signal is an extern and bsd_signal is not declared at all.

What's interesting, bsd_signal was still available as a symbol in NDK r10e android-21 (so there was no linking errors if using r10e), but is not available in NDK r11 and up.

This results in linking errors if used together with libs built with lower NDK levels (e.g. OpenSSL). If you build the libs with android-21 and up (which would just call signal symbol) it would result in *.so failing to load on older Android OS devices due to signal symbol not found.

To link a library built with <android-21 I ended up declaring a bsd_signal wrapper which would call bsd_signal from (it's still available in device's, even up to Android 7.0).

#if (__ANDROID_API__ > 19)
extern "C" {
  typedef __sighandler_t (*bsd_signal_func_t)(int, __sighandler_t);
  bsd_signal_func_t bsd_signal_func = NULL;

  __sighandler_t bsd_signal(int s, __sighandler_t f) {
    if (bsd_signal_func == NULL) {
      // For now (up to Android 7.0) this is always available 
      bsd_signal_func = (bsd_signal_func_t) dlsym(RTLD_DEFAULT, "bsd_signal");

      if (bsd_signal_func == NULL) {
        // You may try dlsym(RTLD_DEFAULT, "signal") or dlsym(RTLD_NEXT, "signal") here
        // Make sure you add a comment here in StackOverflow
        // if you find a device that doesn't have "bsd_signal" in its!!!

        __android_log_assert("", "bsd_signal_wrapper", "bsd_signal symbol not found!");

    return bsd_signal_func(s, f);

PS. Looks like the bsd_signal symbol will be brought back to in NDK r13:

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download