viromedia / virocore

ViroCore cross-platform AR/VR renderer
MIT License
370 stars 108 forks source link

ViroCore SIGSEGV when exiting the Fragment that uses ViroViewARCore #286

Open nuudles opened 5 years ago

nuudles commented 5 years ago

Environment

Please provide the following information about your environment:

  1. OS: Mac
  2. Version: 1.14.0
  3. Device(s): Galaxy S9, Pixel 2

Description

We are using a ViroViewARCore in a fragment. We relay all of the fragment lifecycle events to the ViroViewARCore as such:

    @Override
    public void onStart() {
        super.onStart();
        viroView.onActivityStarted(getActivity());
    }

    @Override
    public void onResume() {
        super.onResume();
        viroView.onActivityResumed(getActivity());
    }

    @Override
    public void onPause() {
        super.onPause();
        viroView.onActivityPaused(getActivity());
    }

    @Override
    public void onStop() {
        super.onStop();
        viroView.onActivityStopped(getActivity());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        viroView.onActivityDestroyed(getActivity());
    }

About 90% of the time when the fragment is destroyed, the app completely crashes with what looks to be a SIGSEGV.

Reproducible Demo

Crash Logs:

E/ACameraDevice: onDeviceIdle sending state cb
I/native: cameras.cc:607 Camera changed state from 4 to 1: Capture session finished streaming.
I/native: android_camera.cc:1240 Capture sequence completed.
I/native: android_camera.cc:1188 Capture session closed for camera 0
I/native: android_camera.cc:730 Reset cleanly got to CLOSED state for camera 0
I/native: cameras.cc:607 Camera changed state from 1 to 0: Camera device closed successfully.
I/native: session.cc:910 Session::Pause returning OK.
I/Viro: AR session paused
D/AudioTrack: stop() called with 530880 frames delivered
D/SurfaceView: BG show() Surface(name=Background for - SurfaceView - com.example.App/com.example.App.activities.mainactivity.MainActivity@7912c5f@0) android.opengl.GLSurfaceView{7912c5f V.E...... ........ 0,0-1080,1992}
D/SurfaceView: surfaceDestroyed 1 android.opengl.GLSurfaceView{7912c5f V.E...... ........ 0,0-1080,1992}
D/: PlayerBase::stop() from IPlayer
D/SurfaceView: BG destroy() Surface(name=Background for - SurfaceView - com.example.App/com.example.App.mainactivity.MainActivity@7912c5f@0) android.opengl.GLSurfaceView{7912c5f V.E...... ........ 0,0-1080,1992}
I/Viro: Destroying ARCore session
I/native: session.cc:841 Entering Session::Pause.
    online_calibration_manager.cc:112 OnlineCalibrationManager: Discarding the new online recalibration estimates.
W/native: analytics_logger.cc:319 Could not send event. Event will be dropped.
I/chatty: uid=10299(u0_a299) Thread-36 identical 5 lines
W/native: analytics_logger.cc:319 Could not send event. Event will be dropped.
I/native: session.cc:872 Session::Pause returning OK.
I/native: session_c_api.cc:621 Deleting ArSession...
D/AudioTrack: stop() called with 0 frames delivered
I/native: feature_combo_node.cc:176 Cleared scoped_image buffers in feature_combo.
A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 7709 (h.example.App)
W/native: analytics_logger.cc:319 Could not send event. Event will be dropped.
V/third_party/redwood/base/jni_common/jni_helper.cc: ~JniHelper: about to detach thread (Called from line 281).
V/third_party/redwood/base/jni_common/jni_helper.cc: ~JniHelper: detached thread (Called from line 281).
nuudles commented 5 years ago

@dam00n Could I provide any more information to be helpful in debugging this issue? As of right now this is a gating issue that is preventing the release of our app as most of the time the app simply crashes when the user leaves the AR experience.

dthian commented 5 years ago

Hey @nuudles, thanks for reaching out, we are currently taking a look at this issue to determine root cause.

dthian commented 5 years ago

Hey @nuudles, to test the above, i've created an activity that toggles between two fragments: First Fragment - An Android Fragment with basic 2D Android UI controls Second Fragment - An ViroARView with AR elements.

As seen in the video below, I am able to toggle between the fragments multiple times and transact between them. As such, I am not able to reproduce the issue you are currently seeing above.

ezgif-5-e817881296e1

One thing i did notice above is that you might be calling the ViroView activity lifecycles within the activity. This only makes sense if the activity is contains the viro view and thus directly handles it.

However, if the ViroView is now contained within a Fragment, because the fragment has it's own lifecycles, the above ViroView lifecycle callbacks thus must be handled in the fragment, Not the activity.

Let me know if you have any additional questions.

nuudles commented 5 years ago

Thanks for the followup @dthian. We're definitely handling the ViroView lifecycle callbacks only in the container fragment. The activity doesn't know anything about the ViroView. Unfortunately it's very hard for us to debug what the issue might be since it's crashing in the ViroCore C framework.

dthian commented 5 years ago

Ah gotcha, one thing i did notice is a crash when mViroView.onActivityDestroyed() is called within the onDestroy callback of the Fragment's lifecycle.

Instead of calling it there, could you instead trigger it within the Fragment's onStop() callback of the lifecycle (right after mViroView.onActivityStopped(getActivity());)?

Looking at Android's Fragment lifecycle, it actually makes more sense to trigger it there instead.

    @Override
    public void onStop() {
        super.onStop();
        mViroView.onActivityStopped(getActivity());
        mViroView.onActivityDestroyed(getActivity());
    }
nuudles commented 5 years ago

@dthian Thanks for the tip. Unfortunately that did not solve the segfault, but we took a closer look and think we found the root cause. We were using a FrameListener to detect user interaction with the scene, specifically by calling getLastCameraPositionRealtime. I guess the callback was still getting called right as the Fragment (and therefore while the ViroView) was being destroyed, and the crash specifically happens when that getLastCameraPositionRealtime gets called. I'm not sure if that is proper behavior or not, but we were able to work around the issue by setting the FrameListener to null on tear down:

    @Override
    public void onStop() {
        super.onStop();
        viroView.setFrameListener(null);
        viroView.onActivityStopped(getActivity());
        viroView.onActivityDestroyed(getActivity());
    }
marcspraragen commented 5 years ago

I'm having the same issue, for what I think is the same reason: getLastCameraPositionRealTime() except I was calling it from mViroView.CameraListener.onTransformUpdate(). I was thinking of using FrameListener instead, and thanks for the tip in any case.