From e3215157e61a948f7372eea4a00bafba2459e3b9 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 15 Sep 2026 02:34:03 +0000 Subject: [PATCH] fix(linux): don't ship libsqlite3.so as a dereferenced symlink The Linux bundle installed lib/libsqlite3.so as a symlink to libsqlite3_flutter_libs_plugin.so, which holds the sqlite3 amalgamation compiled into the plugin. The release tarball dereferences that symlink, so the extracted tree carries two byte-identical copies of the same shared object with the same SONAME. Loading both maps sqlite twice and sqlite3_initialize calls through a null mutex-init pointer, segfaulting about a second after launch before any UI paints. Drop the alias and open the plugin under its real name instead, falling back to the system sqlite when it isn't there. Verified on the v6.4.4 Linux release: restoring a real symlink launches and paints, copying the file back over it reproduces the segfault. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01BkQt8DaFfxs3FThEUaMPix --- cw_core/lib/db/sqlite.dart | 16 ++++++++++++++++ cw_core/pubspec.yaml | 1 + linux/CMakeLists.txt | 7 ------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/cw_core/lib/db/sqlite.dart b/cw_core/lib/db/sqlite.dart index 07297449b..3e91f24a5 100644 --- a/cw_core/lib/db/sqlite.dart +++ b/cw_core/lib/db/sqlite.dart @@ -1,3 +1,4 @@ +import 'dart:ffi'; import 'dart:io'; import 'package:cw_core/db/sqlite_debug.dart'; @@ -5,6 +6,7 @@ import 'package:cw_core/root_dir.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:flutter/foundation.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; +import 'package:sqlite3/open.dart'; import 'package:path/path.dart' as p; Database? db; @@ -49,6 +51,20 @@ Future initDb({String? pathOverride}) async { Future _initDb({String? pathOverride}) async { if (Platform.isLinux || Platform.isWindows) { + if (Platform.isLinux) { + // The Linux bundle only installs the bundled sqlite3 shared object as + // libsqlite3_flutter_libs_plugin.so (see linux/CMakeLists.txt); load it + // directly instead of relying on a libsqlite3.so symlink, which the + // release tarball dereferences into a second copy of the same library + // and crashes the process when both copies get mapped. + open.overrideFor(OperatingSystem.linux, () { + try { + return DynamicLibrary.open('libsqlite3_flutter_libs_plugin.so'); + } catch (_) { + return DynamicLibrary.open('libsqlite3.so.0'); + } + }); + } databaseFactory = databaseFactoryFfi; } diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index b7843f4b1..a5d496474 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -47,6 +47,7 @@ dependencies: bech32: git: url: https://github.com/cake-tech/bech32.git + sqlite3: 3.5.1 sqlite3_flutter_libs: 0.5.40 dev_dependencies: diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index d9466e56e..7a45c054b 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -160,13 +160,6 @@ foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) COMPONENT Runtime) endforeach(bundled_library) -install(CODE " - execute_process( - COMMAND \"${CMAKE_COMMAND}\" -E create_symlink - libsqlite3_flutter_libs_plugin.so - \"${INSTALL_BUNDLE_LIB_DIR}/libsqlite3.so\") -" COMPONENT Runtime) - # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets")