[BUG] Crash on Android when attemping to runOnJS or runAsync
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.
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 Can you help me understand the chances of this hack's success in production mode? Because I'm also facing a similar issue
Hi, I faced with the same
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
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 which workaround did you try? Try this one https://github.com/mrousavy/react-native-vision-camera/issues/2520#issuecomment-2073868718
@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.