cashapp / paparazzi

Render your Android screens without a physical device or emulator
https://cashapp.github.io/paparazzi/
Apache License 2.0
2.3k stars 214 forks source link

Native crash when rendering with shared processes #1065

Open ZacSweers opened 1 year ago

ZacSweers commented 1 year ago

Description

We're unable to record new snapshots for a few tests locally due to a native crash, but unable to figure out why.

I've attached three logs (from three different tests)

hs_err_pid56075.log hs_err_pid56076.log hs_err_pid56077.log

The relevant bit from the trace is

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00000002810b3304, pid=56075, tid=10499
#
# JRE version: OpenJDK Runtime Environment Zulu20.32+11-CA (20.0.2+9) (build 20.0.2+9)
# Java VM: OpenJDK 64-Bit Server VM Zulu20.32+11-CA (20.0.2+9, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-aarch64)
# Problematic frame:
# C  [libandroid_runtime.dylib+0x2cb304]  android::uirenderer::skiapipeline::SkiaHostPipeline::setSurface(ANativeWindow*, android::uirenderer::renderthread::SwapBehavior)+0x9c
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   http://www.azul.com/support/
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

---------------  S U M M A R Y ------------

Command Line: -Djava.awt.headless=true -Djavax.net.ssl.trustStoreType=JKS -Dkotlinx.coroutines.main.delay=true -Dorg.gradle.internal.worker.tmpdir=/Users/zacsweers/dev/slack/android2/libraries/slack-kit/slack-kit/build/tmp/testReleaseUnitTest/work -Dorg.gradle.native=false -Dpaparazzi.artifacts.cache.dir=/Users/zacsweers/.gradle -Dpaparazzi.build.dir=/Users/zacsweers/dev/slack/android2/libraries/slack-kit/slack-kit/build -Dpaparazzi.platform.data.root=/Users/zacsweers/.gradle/caches/transforms-3/944e49004c506aad1fdc12ed40e8c4a9/transformed/layoutlib-native-macarm-2022.2.1-5128371-2 -Dpaparazzi.project.dir=/Users/zacsweers/dev/slack/android2/libraries/slack-kit/slack-kit -Dpaparazzi.test.record=true -Dpaparazzi.test.resources=/Users/zacsweers/dev/slack/android2/libraries/slack-kit/slack-kit/build/intermediates/paparazzi/release/resources.txt -Dpaparazzi.test.verify=false -Drobolectric.graphicsMode=NATIVE --add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED -Xss1m -Xms128m -Xmx1g -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -ea worker.org.gradle.process.internal.worker.GradleWorkerMain 'Gradle Test Executor 4'

Host: "MacBookPro18,3" arm64, 8 cores, 32G, Darwin 22.6.0, macOS 13.5 (22G74)
Time: Mon Aug 28 16:45:21 2023 EDT elapsed time: 18.882621 seconds (0d 0h 0m 18s)

---------------  T H R E A D  ---------------

Current thread (0x000000011d008c00):  JavaThread "Test worker" [_thread_in_native, id=10499, stack(0x000000016be6c000,0x000000016bf6f000)]

Stack: [0x000000016be6c000,0x000000016bf6f000],  sp=0x000000016bf6cb40,  free space=1026k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libandroid_runtime.dylib+0x2cb304]  android::uirenderer::skiapipeline::SkiaHostPipeline::setSurface(ANativeWindow*, android::uirenderer::renderthread::SwapBehavior)+0x9c
C  [libandroid_runtime.dylib+0x2d40c4]  android::uirenderer::renderthread::CanvasContext::setupPipelineSurface()+0x50
C  [libandroid_runtime.dylib+0x2d3e88]  android::uirenderer::renderthread::CanvasContext::setSurface(ANativeWindow*, bool)+0x9c
C  [libandroid_runtime.dylib+0x2d73b8]  android::uirenderer::renderthread::RenderProxy::setSurface(ANativeWindow*, bool)+0x38
C  [libandroid_runtime.dylib+0x297ec4]  android::android_view_ThreadedRenderer_setSurface(_JNIEnv*, _jobject*, long long, _jobject*, unsigned char)+0x54
j  android.graphics.HardwareRenderer.nSetSurface(JLandroid/view/Surface;Z)V+0
j  android.graphics.HardwareRenderer.setSurface(Landroid/view/Surface;Z)V+27
j  android.graphics.HardwareRenderer.setSurface(Landroid/view/Surface;)V+3
j  com.android.layoutlib.bridge.impl.RenderSessionImpl.renderAndBuildResult(ZZ)Lcom/android/ide/common/rendering/api/Result;+343
j  com.android.layoutlib.bridge.impl.RenderSessionImpl.render(Z)Lcom/android/ide/common/rendering/api/Result;+3
j  app.cash.paparazzi.Paparazzi$takeSnapshots$1$2.invoke()V+19
j  app.cash.paparazzi.Paparazzi$takeSnapshots$1$2.invoke()Ljava/lang/Object;+1
j  app.cash.paparazzi.Paparazzi.withTime(JLkotlin/jvm/functions/Function0;)V+76
j  app.cash.paparazzi.Paparazzi.takeSnapshots(Landroid/view/View;Ljava/lang/String;JII)V+356
j  app.cash.paparazzi.Paparazzi.snapshot(Landroid/view/View;Ljava/lang/String;J)V+19
j  app.cash.paparazzi.Paparazzi.snapshot$default(Lapp/cash/paparazzi/Paparazzi;Landroid/view/View;Ljava/lang/String;JILjava/lang/Object;)V+22
j  slack.uikit.components.icon.SKIconSnapshotTest.testSKIcon_Small()V+75
J 13309 c2 java.lang.invoke.DirectMethodHandle$Holder.invokeSpecial(Ljava/lang/Object;Ljava/lang/Object;)V java.base@20.0.2 (14 bytes) @ 0x0000000137dea498 [0x0000000137dea440+0x0000000000000058]
j  java.lang.invoke.LambdaForm$MH+0x000000f001098800.invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+31 java.base@20.0.2
J 12232 c1 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; java.base@20.0.2 (108 bytes) @ 0x0000000131d8dd64 [0x0000000131d8b0c0+0x0000000000002ca4]
j  org.junit.runners.model.FrameworkMethod$1.runReflectiveCall()Ljava/lang/Object;+15
j  org.junit.internal.runners.model.ReflectiveCallable.run()Ljava/lang/Object;+1
j  org.junit.runners.model.FrameworkMethod.invokeExplosively(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+10
j  org.junit.internal.runners.statements.InvokeMethod.evaluate()V+12
j  app.cash.paparazzi.Paparazzi$apply$statement$1.evaluate()V+16
j  app.cash.paparazzi.agent.AgentTestRule$apply$1.evaluate()V+14
j  com.google.testing.junit.testparameterinjector.PluggableTestRunner$ContextMethodRule$1.evaluate()V+20
j  org.junit.runners.BlockJUnit4ClassRunner$1.evaluate()V+11
j  org.junit.runners.ParentRunner.runLeaf(Lorg/junit/runners/model/Statement;Lorg/junit/runner/Description;Lorg/junit/runner/notification/RunNotifier;)V+17
j  org.junit.runners.BlockJUnit4ClassRunner.runChild(Lorg/junit/runners/model/FrameworkMethod;Lorg/junit/runner/notification/RunNotifier;)V+38
j  org.junit.runners.BlockJUnit4ClassRunner.runChild(Ljava/lang/Object;Lorg/junit/runner/notification/RunNotifier;)V+6
j  org.junit.runners.ParentRunner$4.run()V+12
j  org.junit.runners.ParentRunner$1.schedule(Ljava/lang/Runnable;)V+1
j  org.junit.runners.ParentRunner.runChildren(Lorg/junit/runner/notification/RunNotifier;)V+44
j  org.junit.runners.ParentRunner.access$100(Lorg/junit/runners/ParentRunner;Lorg/junit/runner/notification/RunNotifier;)V+2
j  org.junit.runners.ParentRunner$2.evaluate()V+8
j  org.junit.runners.ParentRunner$3.evaluate()V+4
j  org.junit.runners.ParentRunner.run(Lorg/junit/runner/notification/RunNotifier;)V+24
j  org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(Ljava/lang/String;)V+301
j  org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(Ljava/lang/String;)V+12
j  org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(Ljava/lang/Object;)V+5
j  org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(Lorg/gradle/api/internal/tasks/testing/TestClassRunInfo;)V+26
j  org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(Lorg/gradle/api/internal/tasks/testing/TestClassRunInfo;)V+5
j  java.lang.invoke.LambdaForm$DMH+0x000000f001003400.invokeInterface(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V+24 java.base@20.0.2
J 8802 c1 java.lang.invoke.LambdaForm$MH+0x000000f001019400.invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; java.base@20.0.2 (57 bytes) @ 0x00000001310a23d4 [0x00000001310a1b40+0x0000000000000894]
J 7878 c2 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; java.base@20.0.2 (108 bytes) @ 0x0000000137e111e8 [0x0000000137e10f00+0x00000000000002e8]
j  org.gradle.internal.dispatch.ReflectionDispatch.dispatch(Lorg/gradle/internal/dispatch/MethodInvocation;)V+19
j  org.gradle.internal.dispatch.ReflectionDispatch.dispatch(Ljava/lang/Object;)V+5
j  org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(Ljava/lang/Object;)V+22
j  org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;+177
j  jdk.proxy1.$Proxy2.processTestClass(Lorg/gradle/api/internal/tasks/testing/TestClassRunInfo;)V+16 jdk.proxy1
j  org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run()V+34
j  org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(Ljava/lang/Runnable;)V+1
j  org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(Lorg/gradle/process/internal/worker/WorkerProcessContext;)V+80
j  org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(Ljava/lang/Object;)V+5
j  org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(Lorg/gradle/process/internal/worker/WorkerProcessContext;)V+65
j  org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call()Ljava/lang/Void;+293
j  org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call()Ljava/lang/Object;+1
j  worker.org.gradle.process.internal.worker.GradleWorkerMain.run()V+250
j  worker.org.gradle.process.internal.worker.GradleWorkerMain.main([Ljava/lang/String;)V+7
v  ~StubRoutines::call_stub 0x0000000137770140
V  [libjvm.dylib+0x4a9ee0]  JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, JavaThread*)+0x38c
V  [libjvm.dylib+0x518e24]  jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, JavaThread*)+0x158
V  [libjvm.dylib+0x51c5f4]  jni_CallStaticVoidMethod+0x114
C  [libjli.dylib+0x758c]  JavaMain+0x9b8
C  [libjli.dylib+0x98f8]  ThreadJavaMain+0xc
C  [libsystem_pthread.dylib+0x6fa8]  _pthread_start+0x94
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  android.graphics.HardwareRenderer.nSetSurface(JLandroid/view/Surface;Z)V+0
j  android.graphics.HardwareRenderer.setSurface(Landroid/view/Surface;Z)V+27
j  android.graphics.HardwareRenderer.setSurface(Landroid/view/Surface;)V+3
j  com.android.layoutlib.bridge.impl.RenderSessionImpl.renderAndBuildResult(ZZ)Lcom/android/ide/common/rendering/api/Result;+343
j  com.android.layoutlib.bridge.impl.RenderSessionImpl.render(Z)Lcom/android/ide/common/rendering/api/Result;+3
j  app.cash.paparazzi.Paparazzi$takeSnapshots$1$2.invoke()V+19
j  app.cash.paparazzi.Paparazzi$takeSnapshots$1$2.invoke()Ljava/lang/Object;+1
j  app.cash.paparazzi.Paparazzi.withTime(JLkotlin/jvm/functions/Function0;)V+76
j  app.cash.paparazzi.Paparazzi.takeSnapshots(Landroid/view/View;Ljava/lang/String;JII)V+356
j  app.cash.paparazzi.Paparazzi.snapshot(Landroid/view/View;Ljava/lang/String;J)V+19
j  app.cash.paparazzi.Paparazzi.snapshot$default(Lapp/cash/paparazzi/Paparazzi;Landroid/view/View;Ljava/lang/String;JILjava/lang/Object;)V+22
j  slack.uikit.components.icon.SKIconSnapshotTest.testSKIcon_Small()V+75
J 13309 c2 java.lang.invoke.DirectMethodHandle$Holder.invokeSpecial(Ljava/lang/Object;Ljava/lang/Object;)V java.base@20.0.2 (14 bytes) @ 0x0000000137dea498 [0x0000000137dea440+0x0000000000000058]
j  java.lang.invoke.LambdaForm$MH+0x000000f001098800.invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+31 java.base@20.0.2
J 12232 c1 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; java.base@20.0.2 (108 bytes) @ 0x0000000131d8dd64 [0x0000000131d8b0c0+0x0000000000002ca4]
j  org.junit.runners.model.FrameworkMethod$1.runReflectiveCall()Ljava/lang/Object;+15
j  org.junit.internal.runners.model.ReflectiveCallable.run()Ljava/lang/Object;+1
j  org.junit.runners.model.FrameworkMethod.invokeExplosively(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+10
j  org.junit.internal.runners.statements.InvokeMethod.evaluate()V+12
j  app.cash.paparazzi.Paparazzi$apply$statement$1.evaluate()V+16
j  app.cash.paparazzi.agent.AgentTestRule$apply$1.evaluate()V+14
j  com.google.testing.junit.testparameterinjector.PluggableTestRunner$ContextMethodRule$1.evaluate()V+20
j  org.junit.runners.BlockJUnit4ClassRunner$1.evaluate()V+11
j  org.junit.runners.ParentRunner.runLeaf(Lorg/junit/runners/model/Statement;Lorg/junit/runner/Description;Lorg/junit/runner/notification/RunNotifier;)V+17
j  org.junit.runners.BlockJUnit4ClassRunner.runChild(Lorg/junit/runners/model/FrameworkMethod;Lorg/junit/runner/notification/RunNotifier;)V+38
j  org.junit.runners.BlockJUnit4ClassRunner.runChild(Ljava/lang/Object;Lorg/junit/runner/notification/RunNotifier;)V+6
j  org.junit.runners.ParentRunner$4.run()V+12
j  org.junit.runners.ParentRunner$1.schedule(Ljava/lang/Runnable;)V+1
j  org.junit.runners.ParentRunner.runChildren(Lorg/junit/runner/notification/RunNotifier;)V+44
j  org.junit.runners.ParentRunner.access$100(Lorg/junit/runners/ParentRunner;Lorg/junit/runner/notification/RunNotifier;)V+2
j  org.junit.runners.ParentRunner$2.evaluate()V+8
j  org.junit.runners.ParentRunner$3.evaluate()V+4
j  org.junit.runners.ParentRunner.run(Lorg/junit/runner/notification/RunNotifier;)V+24
j  org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(Ljava/lang/String;)V+301
j  org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(Ljava/lang/String;)V+12
j  org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(Ljava/lang/Object;)V+5
j  org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(Lorg/gradle/api/internal/tasks/testing/TestClassRunInfo;)V+26
j  org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(Lorg/gradle/api/internal/tasks/testing/TestClassRunInfo;)V+5
j  java.lang.invoke.LambdaForm$DMH+0x000000f001003400.invokeInterface(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V+24 java.base@20.0.2
J 8802 c1 java.lang.invoke.LambdaForm$MH+0x000000f001019400.invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; java.base@20.0.2 (57 bytes) @ 0x00000001310a23d4 [0x00000001310a1b40+0x0000000000000894]
J 7878 c2 java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; java.base@20.0.2 (108 bytes) @ 0x0000000137e111e8 [0x0000000137e10f00+0x00000000000002e8]
j  org.gradle.internal.dispatch.ReflectionDispatch.dispatch(Lorg/gradle/internal/dispatch/MethodInvocation;)V+19
j  org.gradle.internal.dispatch.ReflectionDispatch.dispatch(Ljava/lang/Object;)V+5
j  org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(Ljava/lang/Object;)V+22
j  org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;+177
j  jdk.proxy1.$Proxy2.processTestClass(Lorg/gradle/api/internal/tasks/testing/TestClassRunInfo;)V+16 jdk.proxy1
j  org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run()V+34
j  org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(Ljava/lang/Runnable;)V+1
j  org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(Lorg/gradle/process/internal/worker/WorkerProcessContext;)V+80
j  org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(Ljava/lang/Object;)V+5
j  org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(Lorg/gradle/process/internal/worker/WorkerProcessContext;)V+65
j  org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call()Ljava/lang/Void;+293
j  org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call()Ljava/lang/Object;+1
j  worker.org.gradle.process.internal.worker.GradleWorkerMain.run()V+250
j  worker.org.gradle.process.internal.worker.GradleWorkerMain.main([Ljava/lang/String;)V+7
v  ~StubRoutines::call_stub 0x0000000137770140

siginfo: si_signo: 11 (SIGSEGV), si_code: 2 (SEGV_ACCERR), si_addr: 0x0000000000000058

Steps to Reproduce I'm unable to reproduce this in a public project so far :/. However, I can share a couple of example tests.

import com.google.testing.junit.testparameterinjector.TestParameter
import com.google.testing.junit.testparameterinjector.TestParameterInjector
import org.junit.Test
import org.junit.runner.RunWith
import slack.test.android.paparazzi.SlackSnapshotTest
import slack.test.android.paparazzi.snapshot.SnapshotFontScales
import slack.test.android.paparazzi.snapshot.SnapshotThemes
import slack.uikit.databinding.SnapshotSkIconBinding
import slack.uikit.resources.R as SlackKitR

@RunWith(TestParameterInjector::class)
class SKIconSnapshotTest(
  @TestParameter fontScale: SnapshotFontScales,
  @TestParameter theme: SnapshotThemes
) : SlackSnapshotTest(fontScale, theme) {

  @Test
  fun testSKIcon_Default() {
    val binding = SnapshotSkIconBinding.inflate(paparazzi.layoutInflater)

    with(binding) {
      iconView.setIcon(SlackKitR.string.mb_icon_jump)
      paparazzi.snapshot(root)
    }
  }

  @Test
  fun testSKIcon_Small() {
    val binding = SnapshotSkIconBinding.inflate(paparazzi.layoutInflater)

    with(binding) {
      iconView.setIcon(SlackKitR.string.mb_icon_jump, SlackKitR.color.sk_sapphire_blue)
      iconView.setIconSize(SlackKitR.dimen.sk_font_icon_size_small)
      paparazzi.snapshot(root)
    }
  }
}

Where the binding is

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:layout_height="@dimen/sk_icon_button_min_size"
    tools:layout_width="@dimen/sk_icon_button_min_size">

    <slack.uikit.components.icon.SKIconView
        android:id="@+id/icon_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:iconSize="@dimen/sk_font_icon_size"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:iconColor="@color/sk_primary_foreground"
        tools:iconResourceId="@string/ts_icon_plus" />

</androidx.constraintlayout.widget.ConstraintLayout>

SKIconView is a simple framelayout that renders icon font internally. SlackPaparazzi is a simple wrapper around Paparazzi with our own defaults.

One thing we have figured out is that they pass when run individually and not in parallel. Another possible thing in common is that these three may be using an icon font under the hood. We're looking more into this as well, but no luck currently.

Expected behavior Not to crash

Additional information:

ZacSweers commented 1 year ago

Actually it seems to not even be parallel dependent as it still fails with max parallelism set to 1. It does work if I set forkEvery to 1, which suggests there's some bad state getting persisted across the JVM.

larryng commented 7 months ago

We're also running into this issue. forkEvery = 1 works as a workaround, but we can't accept the performance cost. Another workaround I found is removing test classes (not individual tests) from the Gradle module that's using Paparazzi. Deleting or moving the classes to another module both work. Pretty weird, but somewhat coincides with how forkEvery works.

Some things that didn't work for me include:

I'm starting to suspect this is an issue with Layoutlib/Skia native rendering on macOS, as this doesn't seem to be an issue on our Linux CI workers.

tauntz commented 3 months ago

For what it's worth, seeing the same issue with:

dekaustubh commented 1 month ago

We are also facing this issue.