Skip to content

Conversation

@DeckerSU
Copy link
Contributor

@DeckerSU DeckerSU commented Nov 2, 2025

On Linux, closing the application window resulted in a crash with the following errors:

  1. embedder.cc (2572): 'FlutterEngineRemoveView' returned 'kInvalidArguments'. Remove view info was invalid. The implicit view cannot be removed.
  2. ** (KomodoWallet): CRITICAL **: FlOpenGLManager *fl_engine_get_opengl_manager(FlEngine *): assertion 'FL_IS_ENGINE(self)' failed
  3. Segmentation fault (core dumped)

Solution

Implemented a workaround that bypasses GTK's standard cleanup chain by calling exit(0) directly:

  1. Dart layer (window_close_handler.dart):

    • Keep using flutter_window_close for the confirmation dialog
    • On Linux, after SDK disposal completes, return false from the close handler to prevent flutter_window_close from closing the window via GTK
    • Manually call exit(0) after a short delay (200ms) to allow cleanup to complete, bypassing GTK cleanup that triggers the crash
  2. Native layer (my_application.cc):

    • Added delete-event handler that returns FALSE to allow the event to propagate to flutter_window_close
    • This ensures the dialog is shown while preventing the problematic GTK cleanup
  3. Platform compatibility:

    • Added conditional import for dart:io exit function to ensure web builds compile correctly

Changes

  • Modified lib/sdk/widgets/window_close_handler.dart to handle Linux exit manually via exit(0)
  • Added conditional exit import with web stub (window_close_handler_exit_stub.dart)
  • Updated linux/my_application.cc with delete-event handler
  • Removed unused flutter_view field from MyApplication struct

Note

⚠️ This is a hackaround solution. Using exit(0) to bypass GTK cleanup is not an ideal approach, as it:

  • Bypasses normal GTK resource cleanup
  • May interrupt ongoing async operations if they take longer than the delay
  • Relies on the OS to clean up resources

This workaround should be replaced with a more proper solution once a fix becomes available / better approach is discovered. The current solution is a temporary measure to prevent application crashes on Linux.

- Updated the window close handler to manage exit behavior on Linux, ensuring graceful shutdown without GTK cleanup issues.
- Added a delete-event signal handler to intercept window close events on Linux, allowing for proper dialog handling before exiting.
- Introduced a stub for the exit function on the web platform to prevent unsupported calls.
- Removed unused flutter_view member from the MyApplication struct and related functions to clean up the code.
- This change simplifies the application structure and addresses potential memory management concerns.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 2, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch patch-fix-linux-crash-on-exit

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Nov 2, 2025

Visit the preview URL for this PR (updated for commit 02dad90):

https://walletrc--pull-3339-merge-5tjokbjf.web.app

(expires Sun, 09 Nov 2025 22:05:42 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: f66a4ff03faa546f12f0ae5a841bd9eff2714dcc

Copy link
Collaborator

@smk762 smk762 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed the mentioned error is no longer present in logs upon exit. When not logged in, linux exits cleanly.

When exiting while logged in, an unrelated error appears - #3341

@DeckerSU
Copy link
Contributor Author

DeckerSU commented Nov 3, 2025

When exiting while logged in, an unrelated error appears - #3341

The error you described isn't related to this PR. It also appears on the latest dev branch without these changes, and I believe it is related to the SSE and SDK shutdown order. You can verify it by compiling the latest "dev" branch, logging in to the wallet, opening any coin to view the transaction history to ensure streaming has started, then exiting the wallet. You will see the following error:

[EventStreamingManager] Enable stream success: type=balance, key=balance:MCL, streamer_id=BALANCE:MCL
[EventStreamingManager] Stream already active: balance:KMD (refCount=1)
[EventStreamingManager] Stream already active: balance:KMD (refCount=2)
[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: Null check operator used on a null value
#0      TransactionHistoryManager.watchTransactions.<anonymous closure>.<anonymous closure> (package:komodo_defi_sdk/src/transaction_history/transaction_history_manager.dart:355)
#1      _runGuarded (dart:async/stream_controller.dart:838)
#2      _BroadcastStreamController._callOnCancel (dart:async/broadcast_stream_controller.dart:357)
#3      _BroadcastStreamController._recordCancel (dart:async/broadcast_stream_controller.dart:236)
#4      _ControllerSubscription._onCancel (dart:async/stream_controller.dart:881)
#5      _BufferingStreamSubscription._cancel (dart:async/stream_impl.dart:293)
#6      _BufferingStreamSubscription._sendDone (dart:async/stream_impl.dart:438)
#7      _DelayedDone.perform (dart:async/stream_impl.dart:592)
#8      _PendingEvents.handleNext (dart:async/stream_impl.dart:678)
#9      _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:649)
#10     _rootRun (dart:async/zone.dart:1517)
#11     _CustomZone.run (dart:async/zone.dart:1422)
#12     _CustomZone.runGuarded (dart:async/zone.dart:1321)
#13     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1362)
#14     _rootRun (dart:async/zone.dart:1525)
#15     _CustomZone.run (dart:async/zone.dart:1422)
#16     _CustomZone.runGuarded (dart:async/zone.dart:1321)
#17     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1362)
#18     _microtaskLoop (dart:async/schedule_microtask.dart:40)
#19     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49)

[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: Bad state: KomodoDefiSdk has been disposed
#0      KomodoDefiSdk._assertNotDisposed (package:komodo_defi_sdk/src/komodo_defi_sdk.dart:248)
#1      KomodoDefiSdk._assertSdkInitialized (package:komodo_defi_sdk/src/komodo_defi_sdk.dart:236)
#2      KomodoDefiSdk.balances (package:komodo_defi_sdk/src/komodo_defi_sdk.dart:294)
#3      LegacyCoinMigrationExtensions.lastKnownUsdBalance (package:web_dex/shared/utils/extensions/legacy_coin_migration_extensions.dart:48)
#4      CoinFiatBalance.build.<anonymous closure> (package:web_dex/shared/widgets/coin_fiat_balance.dart:38)
#5      StreamBuilder.build (package:flutter/src/widgets/async.dart:458)
#6      _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:123)
#7      StatefulElement.build (package:flutter/src/widgets/framework.dart:5833)
#8      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5723)
#9      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5884)
#10     Element.rebuild (package:flutter/src/widgets/framework.dart:5435)
#11     BuildScope._tryRebuild (package:flutter/src/widgets/framework.dart:2695)
#12     BuildScope._flushDirtyElements (package:flutter/src/widgets/framework.dart:2752)
#13     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:3056)
#14     _LayoutBuilderElement._rebuildWithConstraints (package:flutter/src/widgets/layout_builder.dart:271)
#15     RenderAbstractLayoutBuilderMixin.layoutCallback (package:flutter/src/widgets/layout_builder.dart:334)
#16     RenderObjectWithLayoutCallbackMixin.runLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:4156)
#17     RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:2881)
#18     PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1206)
#19     RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2880)
#20     RenderObjectWithLayoutCallbackMixin.runLayoutCallback (package:flutter/src/rendering/object.dart:4156)
#21     _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:448)
#22     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2610)
#23     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1157)
#24     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1170)
#25     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:629)
#26     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:1261)
#27     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:495)
#28     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1434)
#29     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1347)
#30     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1200)
#31     _rootRun (dart:async/zone.dart:1525)
#32     _CustomZone.run (dart:async/zone.dart:1422)
#33     _CustomZone.runGuarded (dart:async/zone.dart:1321)
#34     _invoke (dart:ui/hooks.dart:332)
#35     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:444)
#36     _drawFrame (dart:ui/hooks.dart:302)

[EventStream][IO] SSE Error: HttpException: Connection closed while receiving data, uri = http://127.0.0.1:7783/event-stream?id=0
[EventStream][IO] SSE Error: Reconnecting (attempt 1/3)...
[EventStream][IO] SSE Done: Connection closed by server
[EventStream][IO] SSE Done: Reconnecting (attempt 2/3)...
Error getting version: ConnectionError
[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: Bad state: KomodoDefiSdk has been disposed
#0      KomodoDefiSdk._assertNotDisposed (package:komodo_defi_sdk/src/komodo_defi_sdk.dart:248)
#1      KomodoDefiSdk._assertSdkInitialized (package:komodo_defi_sdk/src/komodo_defi_sdk.dart:236)
#2      KomodoDefiSdk.streaming (package:komodo_defi_sdk/src/komodo_defi_sdk.dart:307)
#3      AuthBloc._listenToAuthStateChanges.<anonymous closure> (package:web_dex/bloc/auth_bloc/auth_bloc.dart:474)
#4      _rootRunUnary (dart:async/zone.dart:1538)
#5      _CustomZone.runUnary (dart:async/zone.dart:1429)
#6      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1329)
#7      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:381)
#8      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:312)
#9      _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:798)
#10     _StreamController._add (dart:async/stream_controller.dart:663)
#11     _rootRunUnary (dart:async/zone.dart:1538)
#12     _CustomZone.runUnary (dart:async/zone.dart:1429)
#13     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1329)
#14     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:381)
#15     _DelayedData.perform (dart:async/stream_impl.dart:573)
#16     _PendingEvents.handleNext (dart:async/stream_impl.dart:678)
#17     _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:649)
#18     _rootRun (dart:async/zone.dart:1517)
#19     _CustomZone.run (dart:async/zone.dart:1422)
#20     _CustomZone.runGuarded (dart:async/zone.dart:1321)
#21     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1362)
#22     _rootRun (dart:async/zone.dart:1525)
#23     _CustomZone.run (dart:async/zone.dart:1422)
#24     _CustomZone.runGuarded (dart:async/zone.dart:1321)
#25     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1362)
#26     _microtaskLoop (dart:async/schedule_microtask.dart:40)
#27     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49)

followed by:

embedder.cc (2572): 'FlutterEngineRemoveView' returned 'kInvalidArguments'. Remove view info was invalid. The implicit view cannot be removed.

** (KomodoWallet:781709): CRITICAL **: 10:09:21.170: FlOpenGLManager *fl_engine_get_opengl_manager(FlEngine *): assertion 'FL_IS_ENGINE(self)' failed
Segmentation fault (core dumped)

The purpose of this PR is to fix the last error. It does not address the Unhandled Exception: Bad state: KomodoDefiSdk has been disposed error. That is a separate issue that should be fixed in another PR. We should probably open a separate issue for it if one does not already exist. The reproduction steps on the dev branch are listed above.

@DeckerSU
Copy link
Contributor Author

DeckerSU commented Nov 3, 2025

When exiting while logged in, an unrelated error appears - #3341

#3345 - for these type of errors Unhandled Exception: Bad state: KomodoDefiSdk has been disposed there is a separate PR.

@smk762 smk762 added this to the v0.9.4 milestone Nov 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants