I am getting a nasty but well known error while working with FFmpeg and NDK:
A/libc(9845): Fatal signal 11 (SIGSEGV), code 1, fault addr 0xa0a9f000 in tid 9921 (AsyncTask #4)
UPDATE
After couple hours i found out that there might be two sources of the problem. One was related to multithreading. I checked it and I fixed it. Now the app crashes ONLY when the video playback (ndk) is on.
I put a "counter" in touch event
surfaceSterowanieKamera.setOnTouchListener(new View.OnTouchListener() {
int counter = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
if ((event.getAction() == MotionEvent.ACTION_MOVE)){
Log.i(TAG, "counter = " + counter);
//cameraMover.setPanTilt(some parameters);
counter++;
}
And I started disabling other app functionalities one by one, but no video. I found out, that with every single functionality less, it takes app longer to crush - counter reaches higher values. After turning off everything besides video playback and touch interface (cameraMover.setPanTilt()
commented out) the app crushes usually when counter is between 1600 - 1700.
In such case logcat shows the above error and GC related info. For me it seems like GC is messing up with the ndk.
01-23 12:27:13.163: I/Display Activity(20633): n = 1649
01-23 12:27:13.178: I/art(20633): Background sticky concurrent mark sweep GC freed 158376(6MB) AllocSpace objects, 1(3MB) LOS objects, 17% free, 36MB/44MB, paused 689us total 140.284ms
01-23 12:27:13.169: A/libc(20633): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x9bd6ec0c in tid 20734 (AsyncTask #3)
Why is GC causing problem with ndk part of application?
ORIGINAL PROBLEM
What am I doing?
I am developing an application that streams live video feed from a webcam and enables user to pan and tilt the remote camera. I am using FFmpeg library built with NDK to achieve smooth playback with little delay.
I am using FFMpeg library to connect to the video stream. Then the ndk part creates bitmap, does the image processing and render frames on the SurfaceView videoSurfaceView
object which is located in the android activity (java part).
To move the webcam I created a separate class - public class CameraMover implements Runnable{/**/}
. This class is a separate thread that connects through sockets with the remote camera and manages tasks connected ONLY with pan-tilt movement.
Next in the main activity i created a touch listener
videoSurfaceView.setOnTouchListener(new View.OnTouchListener() {/**/
cameraMover.setPanTilt(some parameters);
/**/}
which reads user's finger movement and sends commands to the camera.
All tasks - moving camera around, touch interface and video playback are working perfectly when the one of the others is disabled, i.e. when I disable possibility to move camera, I can watch video streaming and register touch events till the end of time (or battery at least). The problem occurs only when task are configured to work simultaneously.
I am unable to find steps to reproduce the problem. It just happens, but only after user touches the screen to move camera. It can be 15 seconds after first interaction, but sometimes it takes app 10 or more minutes to crash. Usually it is something around a minute.
What have I done to fix it?
videoSurfaceView
and assigned touch listener to it. It all ended in the same error.Types of the error
Almost every time the error looks like this:
A/libc(11528): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x9aa9f00c in tid 11637 (AsyncTask #4)
the difference between two errors is the number right after libc, addr number and tid number. Rarely the AsyncTask number varies - i received #1 couple times but I was unable to reproduce it.
Question
How can i avoid this error? What can be the source of it?
The error message that you quoted, libc: Fatal signal 11 (SIGSEGV)
, doesn't say much about what actually happened - this only says that something tried to access memory (either read or write) incorrectly. Since this is a C api, it could be just about anything that is wrong - any use of pointers, use of pointers that are no longer valid, writing too much data into too small a buffer, etc.
So this unfortunately doesn't give much clues - without seeing the relevant C code, it's impossible to say what can cause this.
Normally, the device log also contains some sort of debug info that can give at least a vague hint at where the error occurred - see e.g. easiest way to debug crash in native library, linked by Android app? for an example of this. This post also contains hints about enabling CheckJNI to get better debug info about misuse of JNI functions, which can be one cause of your issues. The NDK also contains the tools ndk-stack
and ndk-gdb
which can be used to get more precise info about where the crash occurs.
Note that even if you get a precise pinpoint of where the crash occurs, that may not directly point to where the bug in the code is.
In this case, when you say that it seems like the GC is causing it, it sounds to me like you are misusing java objects via JNI - as if you are keeping references to java objects without holding the references correctly via JNI. When the GC is run, it may move allocated data around, assuming that nobody is keeping direct pointers to it.
See http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html for some more hints on what it could be.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With