JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.15k stars 1.17k forks source link

Crash when mixing with JavaFx coroutines #17

Closed dector closed 3 years ago

dector commented 4 years ago

I'm migrating existing JavaFx app to current Compose version. Found an issue when trying to render Text():

Log fragment
---------------  T H R E A D  ---------------

Current thread (0x00007fd358873800):  JavaThread "JavaFX Application Thread" [_thread_in_native, id=4109, stack(0x00007fd2c9b45000,0x00007fd2c9c46000)]

Stack: [0x00007fd2c9b45000,0x00007fd2c9c46000],  sp=0x00007fd2c9c3d868,  free space=994k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libfreetype.so.6+0x8a053]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  org.jetbrains.skija.paragraph.Paragraph._nLayout(JF)V+0
j  org.jetbrains.skija.paragraph.Paragraph.layout(F)Lorg/jetbrains/skija/paragraph/Paragraph;+8
j  androidx.compose.ui.text.platform.DesktopParagraphIntrinsics.(Ljava/lang/String;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Ljava/util/List;Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/Font$ResourceLoader;)V+104
j  androidx.compose.ui.text.platform.DesktopParagraphIntrinsicsKt.ActualParagraphIntrinsics(Ljava/lang/String;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Ljava/util/List;Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/Font$ResourceLoader;)Landroidx/compose/ui/text/ParagraphIntrinsics;+50
j  androidx.compose.ui.text.ParagraphIntrinsicsKt.ParagraphIntrinsics(Ljava/lang/String;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Ljava/util/List;Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/Font$ResourceLoader;)Landroidx/compose/ui/text/ParagraphIntrinsics;+46
j  androidx.compose.ui.text.MultiParagraphIntrinsics.(Landroidx/compose/ui/text/AnnotatedString;Landroidx/compose/ui/text/TextStyle;Ljava/util/List;Landroidx/compose/ui/unit/Density;Landroidx/compose/ui/text/font/Font$ResourceLoader;)V+268
j  androidx.compose.ui.text.TextDelegate.layoutIntrinsics(Landroidx/compose/ui/unit/LayoutDirection;)V+72
j  androidx.compose.ui.text.TextDelegate.layoutText(FFLandroidx/compose/ui/unit/LayoutDirection;)Landroidx/compose/ui/text/MultiParagraph;+2
j  androidx.compose.ui.text.TextDelegate.layout-BAnaFRY(JLandroidx/compose/ui/unit/LayoutDirection;Landroidx/compose/ui/text/TextLayoutResult;)Landroidx/compose/ui/text/TextLayoutResult;+206
j  androidx.compose.foundation.text.CoreTextKt$CoreText$10.invoke(Landroidx/compose/ui/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/MeasureScope$MeasureResult;+31
j  androidx.compose.foundation.text.CoreTextKt$CoreText$10.invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+16
j  androidx.compose.ui.LayoutKt$measureBlocksOf$1.measure-2MWCACw(Landroidx/compose/ui/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/MeasureScope$MeasureResult;+22
j  androidx.compose.ui.node.InnerPlaceable.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+22
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayerWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+2
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke()V+11
j  androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke()Ljava/lang/Object;+1
j  androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V+149
j  androidx.compose.ui.platform.DesktopOwner.observeMeasureModelReads(Landroidx/compose/ui/node/LayoutNode;Lkotlin/jvm/functions/Function0;)V+27
j  androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(J)Z+218
j  androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+115
j  androidx.compose.ui.node.LayoutNode.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.foundation.layout.BoxKt$Box$1$1.invoke(Landroidx/compose/ui/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/MeasureScope$MeasureResult;+223
j  androidx.compose.foundation.layout.BoxKt$Box$1$1.invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+16
j  androidx.compose.ui.LayoutKt$MeasuringIntrinsicsMeasureBlocks$1.measure-2MWCACw(Landroidx/compose/ui/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/MeasureScope$MeasureResult;+22
j  androidx.compose.ui.node.InnerPlaceable.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+22
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke()V+11
j  androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke()Ljava/lang/Object;+1
j  androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V+149
j  androidx.compose.ui.platform.DesktopOwner.observeMeasureModelReads(Landroidx/compose/ui/node/LayoutNode;Lkotlin/jvm/functions/Function0;)V+27
j  androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(J)Z+218
j  androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+115
j  androidx.compose.ui.node.LayoutNode.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.platform.DesktopSelectionKt$Wrap$1$1.invoke(Landroidx/compose/ui/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/MeasureScope$MeasureResult;+92
j  androidx.compose.ui.platform.DesktopSelectionKt$Wrap$1$1.invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+16
j  androidx.compose.ui.LayoutKt$MeasuringIntrinsicsMeasureBlocks$1.measure-2MWCACw(Landroidx/compose/ui/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/MeasureScope$MeasureResult;+22
j  androidx.compose.ui.node.InnerPlaceable.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+22
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke()V+11
j  androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke()Ljava/lang/Object;+1
j  androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V+149
j  androidx.compose.ui.platform.DesktopOwner.observeMeasureModelReads(Landroidx/compose/ui/node/LayoutNode;Lkotlin/jvm/functions/Function0;)V+27
j  androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(J)Z+218
j  androidx.compose.ui.node.OuterMeasurablePlaceable.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+115
j  androidx.compose.ui.node.LayoutNode.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.RootMeasureBlocks.measure-2MWCACw(Landroidx/compose/ui/MeasureScope;Ljava/util/List;J)Landroidx/compose/ui/MeasureScope$MeasureResult;+60
j  androidx.compose.ui.node.InnerPlaceable.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+22
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+5
j  androidx.compose.ui.node.LayerWrapper.performMeasure-BRTryo0(J)Landroidx/compose/ui/Placeable;+2
j  androidx.compose.ui.node.LayoutNodeWrapper.measure-BRTryo0(J)Landroidx/compose/ui/Placeable;+7
j  androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke()V+11
j  androidx.compose.ui.node.OuterMeasurablePlaceable$remeasure$2.invoke()Ljava/lang/Object;+1
j  androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;+110
j  androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V+123
j  androidx.compose.ui.platform.DesktopOwner.observeMeasureModelReads(Landroidx/compose/ui/node/LayoutNode;Lkotlin/jvm/functions/Function0;)V+27
j  androidx.compose.ui.node.OuterMeasurablePlaceable.remeasure-BRTryo0(J)Z+218
j  androidx.compose.ui.node.LayoutNode.remeasure-BRTryo0$ui(J)Z+5
j  androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure(Landroidx/compose/ui/node/LayoutNode;)Z+13
j  androidx.compose.ui.node.MeasureAndLayoutDelegate.access$doRemeasure(Landroidx/compose/ui/node/MeasureAndLayoutDelegate;Landroidx/compose/ui/node/LayoutNode;)Z+2
j  androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout()Z+186
j  androidx.compose.ui.platform.DesktopOwner.draw(Lorg/jetbrains/skija/Canvas;)V+11
j  androidx.compose.ui.platform.DesktopOwners.onRender(Lorg/jetbrains/skija/Canvas;IIJ)V+56
j  androidx.compose.desktop.OwnersRenderer.onRender(Lorg/jetbrains/skija/Canvas;IIJ)V+16
j  androidx.compose.desktop.FrameSkiaLayer.preparePicture(J)V+70
j  androidx.compose.desktop.FrameSkiaLayer.access$preparePicture(Landroidx/compose/desktop/FrameSkiaLayer;J)V+2
j  androidx.compose.desktop.FrameSkiaLayer$wrapped$1.redrawLayer()V+11
j  androidx.compose.desktop.FrameSkiaLayer.onFrame(J)V+9
j  androidx.compose.desktop.FrameSkiaLayer.access$onFrame(Landroidx/compose/desktop/FrameSkiaLayer;J)V+2
j  androidx.compose.desktop.FrameSkiaLayer$frameDispatcher$1.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;+40
j  androidx.compose.desktop.FrameSkiaLayer$frameDispatcher$1.invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+15
j  androidx.compose.desktop.FrameDispatcher$job$1.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;+135
j  kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(Ljava/lang/Object;)V+46
j  kotlinx.coroutines.DispatchedTask.run()V+334
j  com.sun.javafx.application.PlatformImpl.lambda$runLater$10(Ljava/lang/Runnable;)Ljava/lang/Void;+1
j  com.sun.javafx.application.PlatformImpl$$Lambda$192.run()Ljava/lang/Object;+4
v  ~StubRoutines::call_stub
j  java.security.AccessController.doPrivileged(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;+0 java.base@11.0.8
j  com.sun.javafx.application.PlatformImpl.lambda$runLater$11(Ljava/lang/Runnable;Ljava/security/AccessControlContext;)V+7
j  com.sun.javafx.application.PlatformImpl$$Lambda$191.run()V+8
j  com.sun.glass.ui.InvokeLaterDispatcher$Future.run()V+4
v  ~StubRoutines::call_stub
j  com.sun.glass.ui.gtk.GtkApplication._runLoop(Ljava/lang/Runnable;Z)V+0
j  com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(Ljava/lang/Runnable;Z)V+7
j  com.sun.glass.ui.gtk.GtkApplication$$Lambda$179.run()V+12
j  java.lang.Thread.run()V+11 java.base@11.0.8
v  ~StubRoutines::call_stub

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

This happens only when Text() is present in hierarchy AND javafx coroutines are included as a dependency.

Here is MRS (open it in IDEA and run MainKt - app will crash almost instantly).

compose-issue.zip

olonho commented 4 years ago

Interesting problem, seems Swing (used by Compose) and JavaFX coroutine dispatchers cannot coexist. So not sure, if such a config is supported. Is it possible to not use JFX coroutine dispatcher?

dector commented 4 years ago

Not a major issue for me TBH - I was going to rewrite JavaFX granulary but now I'll just write Compose GUI as a separate app.

So, there is no need to waste time on fixing this.

pacher commented 3 years ago

So, there is no need to waste time on fixing this.

Please do waste time on fixing this. I just saw the announcement and will start to migrate to Compose from JavaFx today. But it can not be all done in once, there will be things missing etc. So Compose and JavaFx will co-exist for quite some time for me (I am planning to have JavaFx in different pop-up windows)

And anyway it is quite puzzling to me how is the simple presence of different dispatcher can cause an issue. What if I want to write or use other non-standard dispatchers? What causes the issue? What to look out for?

mel4tonin4 commented 3 years ago

I'd like to gradually experiment with Compose in a JavaFx application which is the desktop version and the control panel of the supporting service of a mobile application, and this is a showstopper for me, too. Please, do not ignore this issue.

olonho commented 3 years ago

@igordmn IIRC you had simple fix with more explicit dispatcher selector. Can we apply it and check if it helps?

pacher commented 3 years ago

Wild guess: just find and replace Dispatchers.Main with Dispatchers.Swing in compose codebase?

olonho commented 3 years ago

@dector could you please check if issue has gone with the build "0.2.0-build123"?

dector commented 3 years ago

@olonho 0.2.0-build123 fixes this issue for my sample.

okushnikov commented 3 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.