I have a library with ndk code library which is throwing a sigdev on a particular device I have, which kills my app. Is it possible to catch this sigdev and throw a Java exception? The catch must be done without modification to the library which is throwing the exception.
The exception looks like so:
01-26 09:09:38.610 19393-19869/com.foo.bar A/libc: /Volumes/Android/buildbot/src/android/ndk-r12-release/ndk/sources/cxx-stl/llvm-libc++abi/libcxxabi/src/abort_message.cpp:74: void abort_message(const char *, ...): assertion "terminating with uncaught exception of type char const*" failed
01-26 09:09:38.610 19393-19869/com.foo.bar A/libc: Fatal signal 6 (SIGABRT) at 0x00004bc1 (code=-6), thread 19869 (Thread-9201)
There are similar questions asked elsewhere on SO, however it seems that in those cases they control both the NDK and the Java sourc, and use the ndk code to trigger a java exception. In my situation I do not have any control over the ndk code, it is a closed source library, so I must handle it entirely via the Java code, or additional ndk code of my own creation.
You can't catch native exceptions in Java, but you can catch them from C++ and turn them into Java exceptions via a wrapper library. Call your wrapper from Java rather than the original library and let your wrapper library delegate the work but handle exceptions.
This may not work, as catching exceptions across shared library boundaries most likely requires that both libraries are built with RTTI, exceptions, and are using the same STL.
Related
I am writing native code on Android and CPP exceptions are disabled by default.
I could simply enable them but I love leaving settings to default.
So I wonder if I can use all features of libc++ if exceptions are disabled?
Here is one code example:
std::__fs::filesystem::directory_iterator it("/does/not/exist");
The libc++ is compiled with exceptions. So this line will throw an exception. But I cannot catch it because my code is compiled without exceptions. My program will crash because an exception of type filesystem_error is thrown and I did not catch it:
terminating with uncaught exception of type std::__ndk1::__fs::filesystem::filesystem_error: filesystem error: in directory_iterator::directory_iterator(...): No such file or directory [/does/not/exist]
/buildbot/src/android/ndk-release-r23/toolchain/llvm-project/libcxx/../../../toolchain/llvm-project/libcxxabi/src/abort_message.cpp:72: abort_message: assertion "terminating with uncaught exception of type std::__ndk1::__fs::filesystem::filesystem_error: filesystem error: in directory_iterator::directory_iterator(...): No such file or directory [/does/not/exist]" failed
Aborted
So my question is if it is possible to use full libc++ if exceptions are disabled in my code?
Edit:
I am building a native standalone executable using ndk-build.
I am seeing a very strange failure that is very similar to the problem described in
dynamic_cast on llvm clang compiler failing: dynamic_cast returns nullptr when I am trying to downcast from base type to derived type, for an object of derived type. In my case though typeid actually shows the same dynamic type.
Below is the debug function that I use to verify run-time types. It takes a pointer of SrcType* and tries to dynamically cast it to pointer of DstType*. If conversion fails, i.e. the returned pointer is nullptr, it prints an error message. VERIFY() macro checks if condition is true:
template<typename DstType, typename SrcType>
void CheckDynamicType( SrcType *pSrcPtr )
{
VERIFY(dynamic_cast<DstType*> (pSrcPtr) != nullptr,
"Dynamic type cast failed. Src typeid: \'", typeid(*pSrcPtr).name(),
"\' Dst typeid: \'", typeid(DstType).name(), '\'');
}
And here is the output that I am getting:
Dynamic type cast failed. Src typeid: 'N8Diligent15RefCountersImplE' Dst typeid: 'N8Diligent15RefCountersImplE'
I am using clang compiler from Android ndk r16 toolchain. I am compiling with rtti flag. The same code works fine on gcc and msvc.
Another bit of information: the code also works fine if I build it with gnustl runtime (I am not sure how gnu stl works with clang, but anyway).
UPDATE
After spending few more hours looking into the issue I found out that dynamic_cast fails when it is used on the object created in another module.
From this
Using clang++, -fvisibility=hidden, and typeinfo, and type-erasure and this posts it looks like dynamic_cast should work if the class is labeled with __attribute__((visibility("default"))) so that typeid structures from two modules will be merged. This, however does not help either and I am still seeing the issue.
If you’re using the stock system compiler there’s a near 0 chance dynamic_cast of the compiler isn’t working. This is tested and used extensively in everything from system software up.
Being new to Android NDK Caffe, I would like to use built version in my Android project. I tried to run this built sample demo, but while running, it showed the following:
03-26 14:46:35.697 2800-3042/com.sh1r0.caffe_android_demo A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 3042 (AsyncTask #1)
(the app crashed)
I can see that the sigsev signal is thrown through android AsyncTask.
The problem could come from this function.
caffeMobile.predictImage(strings[0])[0]; //line 160 of MainActivity
This signal comes from JNI and it is very difficult to know where is the problem unless you can debug natively (through ndk) the app. The caffe-sample is not configured to debug on native method.
Try this issues to manage the error:
Ensure that your image path in this string[0] arrays are not empty. and exists.
Ensure that the other caffeMobile functions are able to exec without
problems, for example:
caffeMobile = new CaffeMobile();
caffeMobile.setNumThreads(4);
caffeMobile.loadModel("/sdcard/caffe_mobile/bvlc_reference_caffenet/deploy.prototxt", "/sdcard/caffe_mobile/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel");
If you are able to execute the other functions, probably your image path is not correct, check.
If you are not able to execute loadModel or setNumThreads function, probably the apk is not loading libjni.so library correctly , or the jni bridge is not able to locate jni functions.
I have a native application that always worked on Android KitKat with both Dalivik and ART runtimes, but it now crashes on Android L with the following trace:
E/art(12810): dlopen("/data/app-lib/com.mylib.example", RTLD_LAZY) failed: dlopen failed: cannot locate symbol "issetugid" referenced by "mylib.so"...
D/AndroidRuntime(12810): Shutting down VM
E/AndroidRuntime(12810): FATAL EXCEPTION: main
E/AndroidRuntime(12810): Process: com.mylib.example, PID: 12810
E/AndroidRuntime(12810): java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "issetugid" referenced by "mylib.so"...
E/AndroidRuntime(12810): at java.lang.Runtime.loadLibrary(Runtime.java:364)
E/AndroidRuntime(12810): at java.lang.System.loadLibrary(System.java:610)
Is ART runtime in Android L different from KitKat? There is no new NDK available yet, therefore, how to avoid this crash, because it seems that the function issetugid is no longer supported.
The issue has been fixed in the final Android 5.0 release. There is no need to re-compile existing binaries.
However, if the native lib is compiled with target android-21, it fails on previous Android versions (< 5.0)
I think i may have the answer, please correct me if iam wrong.I had faced similar issue and now its fixed (or i have found a workaround rather)
while registering native method to JNI, there are two ways of doing it.
1) Implement JNI_OnLoad() method in your .cpp file and register your native methods with the
appropriate classes.
Check- http://developer.android.com/training/articles/perf-jni.html#native_libraries
example - https://android.googlesource.com/platform/development/+/master/samples/SimpleJNI/jni/native.cpp
2) there is a particular naming convention to follow for the native methods, where the class path (including package) have to be added.
Check - http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615
Here we need not implement any method. The JVM discovers the native method from the symbol names it self from the binary.
The first method doesn't seem to work in Android ART runtime (ART is Optional in kitkat and it will be the only runtime in Lolipop).I am not not sure why it doesnt work. but i think the reason is because the way ART performs.(The bytecodes are converted and cached during install time itself instead of runtime, so that app runs faster). So since the native libs are not loaded (on_load is not called) the conversion to machine code fails at some point
Use the second method to register natives. it should work.
Only disadvantage is now your function names will be and long and will look horrible (i bet none of the function will fit in 100char limit).bye bye function name readability.
Hope this helps
Cheers,
Shrish
I'm porting some C++ code to Android using NDK and GCC. The code basically runs. At one point, when debugging in Eclipse, the call
Dabbler::Android::Factory* pFactory = new Dabbler::Android::Factory;
causes this error:
Thread [1] (Suspended: Signal 'SIGILL' received. Description: Illegal instruction.)
1 <symbol is not available> 0x812feb44
What does that mean? Has the compiler generated illegal code for some reason? I have a breakpoint in the constructor (which does nothing), and it's not hit. I have already done a full rebuild.
What could I be doing wrong to cause this problem?
Make sure that all functions with non-void return type have a return statement.
While some compilers automatically provide a default return value, others will send a SIGILL or SIGTRAP at runtime when trying to leave a function without a return value.
It means the CPU attempted to execute an instruction it didn't understand. This could be caused by corruption I guess, or maybe it's been compiled for the wrong architecture (in which case I would have thought the O/S would refuse to run the executable). Not entirely sure what the root issue is.
It could be some un-initialized function pointer, in particular if you have corrupted memory (then the bogus vtable of C++ bad pointers to invalid objects might give that).
BTW gdb watchpoints & tracepoints, and also valgrind might be useful (if available) to debug such issues. Or some address sanitizer.
LeetCode's online compiler and dev environment generates SIGILL errors for mistakes that do not generate the same error in my desktop IDE.
For example, array access with an out-of-bounds index:
["foo", "bar"][2]
LeetCode's compiler shows only the error:
Runtime Error
process exited with signal SIGILL
in a local Xcode playground this same code instead results in the error:
error: Execution was interrupted, reason: EXC_BREAKPOINT (code=1, subcode=0x18f2ea5d8).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
Only in a full Xcode project compilation and run does it report the actual error:
Thread 1: Fatal error: Index out of range