react-native-worklets-core icon indicating copy to clipboard operation
react-native-worklets-core copied to clipboard

[BUG] Crash on Android when attemping to runOnJS or runAsync

Open wdoyle2 opened this issue 1 year ago • 7 comments

Hey there,

When attempting to use the following code:

  const frameProcessor = useFrameProcessor(
    frame => {
      'worklet';
      console.log('test');
    
      runAsync(frame, () => {
        'worklet';
        console.log('test2');
      });
    },
    [],
  );

with @mrousavy react-vision-camera library the entire Android app crashes. on iOS is perfectly fine with no isses.

Logs:

2025-01-06 15:18:08.765 15044-15724 ImageReader_JNI         com.swinghub.android                 W  Unable to acquire a buffer item, very likely client tried to acquire more than maxImages buffers
2025-01-06 15:18:08.766 15044-15724 ImageAnalysisAnalyzer   com.swinghub.android                 E  Failed to acquire image.
                                                                                                    java.lang.IllegalStateException: maxImages (6) has already been acquired, call #close before acquiring more.
                                                                                                    	at android.media.ImageReader.acquireNextImage(ImageReader.java:513)
                                                                                                    	at androidx.camera.core.AndroidImageReaderProxy.acquireNextImage(AndroidImageReaderProxy.java:86)
                                                                                                    	at androidx.camera.core.SafeCloseImageReaderProxy.acquireNextImage(SafeCloseImageReaderProxy.java:86)
                                                                                                    	at androidx.camera.core.ImageAnalysisBlockingAnalyzer.acquireImage(ImageAnalysisBlockingAnalyzer.java:39)
                                                                                                    	at androidx.camera.core.ImageAnalysisAbstractAnalyzer.onImageAvailable(ImageAnalysisAbstractAnalyzer.java:126)
                                                                                                    	at androidx.camera.core.SafeCloseImageReaderProxy.lambda$setOnImageAvailableListener$1$androidx-camera-core-SafeCloseImageReaderProxy(SafeCloseImageReaderProxy.java:211)
                                                                                                    	at androidx.camera.core.SafeCloseImageReaderProxy$$ExternalSyntheticLambda0.onImageAvailable(D8$$SyntheticClass:0)
                                                                                                    	at androidx.camera.core.AndroidImageReaderProxy.lambda$setOnImageAvailableListener$0$androidx-camera-core-AndroidImageReaderProxy(AndroidImageReaderProxy.java:167)
                                                                                                    	at androidx.camera.core.AndroidImageReaderProxy$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
                                                                                                    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
                                                                                                    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
                                                                                                    	at java.lang.Thread.run(Thread.java:929)
2025-01-06 15:18:08.886 15044-15265 libc                    com.swinghub.android                 A  Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x75d3cc2fb0 in tid 15265 (ionCamera.video), pid 15044 (winghub.android)
2025-01-06 15:18:08.938 15044-15667 CameraView              com.swinghub.android                 I  invokeOnAverageFpsChanged(NaN)
2025-01-06 15:18:09.106 15733-15733 DEBUG                   pid-15733                            A  pid: 15044, tid: 15265, name: ionCamera.video  >>> com.swinghub.android <<<
2025-01-06 15:18:09.107 15733-15733 DEBUG                   pid-15733                            A        #05 pc 00000000003cd920  /data/app/com.swinghub.android-JILhOcVL9UeWxRMsrjHXNw==/base.apk!libjsc.so (offset 0x9720000) (BuildId: 9cb83e4124e3ee1471bc717c722b4109614385ba)
2025-01-06 15:18:09.107 15733-15733 DEBUG                   pid-15733                            A        #06 pc 00000000002622dc  /data/app/com.swinghub.android-JILhOcVL9UeWxRMsrjHXNw==/base.apk!libjsc.so (offset 0x9720000) (JSStringCreateWithUTF8CString+20) (BuildId: 9cb83e4124e3ee1471bc717c722b4109614385ba)
---------------------------- PROCESS STARTED (15735) for package com.swinghub.android ----------------------------

Version: "react-native": "0.76.5", "react-native-vision-camera": "^4.6.3", "react-native-vision-camera-face-detector": "^1.7.2", "react-native-worklets-core": "^1.5.0",

Babel:

    //['transform-remove-console'],
    ['react-native-worklets-core/plugin'],
    [
      'react-native-reanimated/plugin',
      {
        processNestedWorklets: true,
      },
    ],

However did try babel without the core/plugin and kept re-animated but still an issue.

wdoyle2 avatar Jan 06 '25 15:01 wdoyle2

This is a hack that allows me to transmit the data outside the scope of the worklet. Not great but still better than a crash


 const facesRef = useSharedValue<any>([]);

  
  const monitor = setInterval(() => {
    if(facesRef.value.length > 0) {
      handleFacesDetected({ faces: facesRef.value });
    }
  }, 1000);
 
  const frameProcessor = useFrameProcessor((frame) => {
    'worklet';
    const faces = detectFaces(frame);
    if (faces.length === 0) return;
    facesRef.value = faces;
  }, []);

wdoyle2 avatar Jan 06 '25 16:01 wdoyle2

@wdoyle2 Can you help me understand the chances of this hack's success in production mode? Because I'm also facing a similar issue

PriyaJainDev avatar Jan 07 '25 19:01 PriyaJainDev

Hi, I faced with the same

YuriOlepir avatar Jan 31 '25 13:01 YuriOlepir

It seems this issue is similar to this one: https://github.com/mrousavy/react-native-vision-camera/issues/2820 ps: there is a workaround mentioned in the link

ghashi avatar Feb 05 '25 23:02 ghashi

I have a similar issue. Works well on dev, but prod/preview fails. Sentry reports a SIGSEGV SegFault RNWorklet::JsiWorkletContext::invokeOnWorkletThread, and the workaround doesn't cut it. Parts of the offending code:

const handleDetectedFaces = Worklets.createRunOnJS((
    faces: Face[]
  ) => {
    if (faces.length === 1) {
      setTakingPictureAllowed(true);
    } else {
      setTakingPictureAllowed(false);
    }
  });

  const frameProcessor = useFrameProcessor((frame) => {
    'worklet';
    if (!isVisible || capturedPhotoUri) { return; } // Only process frames if visible and not showing preview
    runAsync(frame, () => {
      'worklet';
      const faces = detectFaces(frame);
      handleDetectedFaces(faces);
    });
  }, [isVisible, capturedPhotoUri, handleDetectedFaces]);

  // ...

  <Camera
    ref={camera}
    style={StyleSheet.absoluteFill}
    device={device}
    photo={true}
    isActive={isVisible && !capturedPhotoUri} // Camera is active only if modal is visible and no photo is captured
    frameProcessor={frameProcessor}
  />

I guess I could settle for not using the face detector plugin and that would be it... But it would remove a nice feature from the app. Sad.

JerryBels avatar May 16 '25 15:05 JerryBels

@JerryBels which workaround did you try? Try this one https://github.com/mrousavy/react-native-vision-camera/issues/2520#issuecomment-2073868718

jslok avatar May 16 '25 16:05 jslok

@jslok thanks, didn't see that before! I'll try it, even though it's a dirty one - modifying node_modules, and also mrousavy says it's not a proper solution, so it will need to be rolled back at some point.

JerryBels avatar May 20 '25 19:05 JerryBels