From 98934d10b180a4e83028fc855d718dfe733b2a74 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 8 Sep 2026 19:51:10 -0700 Subject: [PATCH 1/2] feat: DartBridge.hardExit, and re-pin python-build to 20260908 dart:io's exit() runs the normal C teardown, which destroys the C++ statics inside every loaded CPython extension module. The interpreter lives on a detached thread that may still be running, so that teardown can fault it, giving a SIGSEGV on exit from an app that had already finished its work. The reported case died in matplotlib's ft2font looking up a pybind11 type-caster map that had just been destructed. hardExit routes to serious_python_hard_exit in dart_bridge 1.9.0, which terminates without running atexit handlers or static destructors. The symbol is resolved through the existing _lookupOrNull soft lookup, so an app built against an older libdart_bridge still loads; canHardExit is then false and the caller falls back to exit(). Version tables regenerated from python-build release 20260908, which carries dart_bridge 1.9.0. No CPython or Pyodide versions change. --- src/serious_python/CHANGELOG.md | 5 ++++ src/serious_python/lib/bridge.dart | 3 ++- .../lib/src/python_versions.dart | 6 ++--- src/serious_python/pubspec.yaml | 2 +- .../android/python_versions.properties | 6 ++--- src/serious_python_android/pubspec.yaml | 2 +- .../darwin/python_versions.properties | 6 ++--- src/serious_python_darwin/pubspec.yaml | 2 +- .../linux/python_versions.properties | 6 ++--- src/serious_python_linux/pubspec.yaml | 2 +- .../lib/src/dart_bridge_ffi.dart | 25 +++++++++++++++++++ .../pubspec.yaml | 2 +- src/serious_python_windows/pubspec.yaml | 2 +- .../windows/python_versions.properties | 6 ++--- 14 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/serious_python/CHANGELOG.md b/src/serious_python/CHANGELOG.md index 357ea222..600e9631 100644 --- a/src/serious_python/CHANGELOG.md +++ b/src/serious_python/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.7.0 + +* **`DartBridge.hardExit(exitCode)`: terminate without running process teardown.** `dart:io`'s `exit()` runs the normal C teardown, which destroys the C++ statics inside every loaded CPython extension module. The interpreter lives on a detached thread that may still be running, so that teardown can fault it, giving a `SIGSEGV` on exit from an app that had already finished its work. `hardExit` skips it. Guard with `DartBridge.canHardExit`, which is `false` against a pre-1.9.0 `libdart_bridge` (the symbol is resolved softly, like `isPythonInitialized` and `signalDartSession`); `hardExit` is then a no-op and the caller should fall back to `exit()`. +* Bundled python-build snapshot re-pinned to [20260908](https://github.com/flet-dev/python-build/releases/tag/20260908) (`dart_bridge` **1.8.0 -> 1.9.0**), which is what carries the new `serious_python_hard_exit` export. No CPython or Pyodide versions change; the release exists to publish the updated manifest. + ## 4.6.0 * **The bundled CPython runtimes move to 3.12.14 / 3.13.15 / 3.14.7** (from 3.12.13 / 3.13.14 / 3.14.6) — the first Python version move since 4.3.x; every prior 4.4/4.5 release re-pinned python-build without changing a Python version. All three are security releases: they fix a quadratic-complexity DoS in incremental `html.parser.HTMLParser` parsing ([gh-153030](https://github.com/python/cpython/issues/153030)) and quadratic behaviour in `xml.etree.ElementTree` XPath index predicates ([gh-152674](https://github.com/python/cpython/issues/152674)), among others. diff --git a/src/serious_python/lib/bridge.dart b/src/serious_python/lib/bridge.dart index b1e4b51c..4abc29f0 100644 --- a/src/serious_python/lib/bridge.dart +++ b/src/serious_python/lib/bridge.dart @@ -3,7 +3,8 @@ /// See [PythonBridge] for the per-channel API. The lower-level [DartBridge] /// singleton (from the platform-interface package) is re-exported here for /// embedders that need the process-reuse / session-restart hooks added in -/// libdart_bridge 1.3.0 — `isPythonInitialized` and `signalDartSession`. +/// libdart_bridge 1.3.0 (`isPythonInitialized` and `signalDartSession`), or +/// the teardown-skipping `hardExit` added in 1.9.0. library; export 'package:serious_python_platform_interface/src/dart_bridge_ffi.dart' diff --git a/src/serious_python/lib/src/python_versions.dart b/src/serious_python/lib/src/python_versions.dart index 9f1aaa08..3caef1e5 100644 --- a/src/serious_python/lib/src/python_versions.dart +++ b/src/serious_python/lib/src/python_versions.dart @@ -1,5 +1,5 @@ // GENERATED by `dart run serious_python:gen_version_tables` from python-build's -// manifest.json (release 20260902). Do not edit by hand — edit python-build's +// manifest.json (release 20260908). Do not edit by hand — edit python-build's // manifest.json, cut a release, bump `pythonReleaseDate`, and regenerate. const pythonVersionEnvironmentVariable = "SERIOUS_PYTHON_VERSION"; @@ -10,8 +10,8 @@ const pyodideVersionEnvironmentVariable = "SERIOUS_PYTHON_PYODIDE_VERSION"; const dartBridgeVersionEnvironmentVariable = "DART_BRIDGE_VERSION"; /// python-build release the bundled runtimes come from (YYYYMMDD). -const pythonReleaseDate = "20260902"; -const dartBridgeVersion = "1.8.0"; +const pythonReleaseDate = "20260908"; +const dartBridgeVersion = "1.9.0"; const defaultPythonVersion = "3.14"; class PythonRelease { diff --git a/src/serious_python/pubspec.yaml b/src/serious_python/pubspec.yaml index ed0a1095..d9b77569 100644 --- a/src/serious_python/pubspec.yaml +++ b/src/serious_python/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python description: A cross-platform plugin for adding embedded Python runtime to your Flutter apps. homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 4.6.0 +version: 4.7.0 platforms: ios: diff --git a/src/serious_python_android/android/python_versions.properties b/src/serious_python_android/android/python_versions.properties index b4703e82..e197b9b8 100644 --- a/src/serious_python_android/android/python_versions.properties +++ b/src/serious_python_android/android/python_versions.properties @@ -1,8 +1,8 @@ # GENERATED by `dart run serious_python:gen_version_tables` from -# python-build manifest.json (release 20260902). Do not edit by hand. +# python-build manifest.json (release 20260908). Do not edit by hand. default_python_version=3.14 -dart_bridge_version=1.8.0 -python_build_release_date=20260902 +dart_bridge_version=1.9.0 +python_build_release_date=20260908 3.12.full_version=3.12.14 3.12.android_abis=arm64-v8a,x86_64,armeabi-v7a 3.13.full_version=3.13.15 diff --git a/src/serious_python_android/pubspec.yaml b/src/serious_python_android/pubspec.yaml index 05abd88f..3c152a99 100644 --- a/src/serious_python_android/pubspec.yaml +++ b/src/serious_python_android/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_android description: Android implementation of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 4.6.0 +version: 4.7.0 environment: sdk: ">=3.0.0 <4.0.0" diff --git a/src/serious_python_darwin/darwin/python_versions.properties b/src/serious_python_darwin/darwin/python_versions.properties index b4703e82..e197b9b8 100644 --- a/src/serious_python_darwin/darwin/python_versions.properties +++ b/src/serious_python_darwin/darwin/python_versions.properties @@ -1,8 +1,8 @@ # GENERATED by `dart run serious_python:gen_version_tables` from -# python-build manifest.json (release 20260902). Do not edit by hand. +# python-build manifest.json (release 20260908). Do not edit by hand. default_python_version=3.14 -dart_bridge_version=1.8.0 -python_build_release_date=20260902 +dart_bridge_version=1.9.0 +python_build_release_date=20260908 3.12.full_version=3.12.14 3.12.android_abis=arm64-v8a,x86_64,armeabi-v7a 3.13.full_version=3.13.15 diff --git a/src/serious_python_darwin/pubspec.yaml b/src/serious_python_darwin/pubspec.yaml index 988a5549..b9cb99d5 100644 --- a/src/serious_python_darwin/pubspec.yaml +++ b/src/serious_python_darwin/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_darwin description: iOS and macOS implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 4.6.0 +version: 4.7.0 environment: # The Swift Package Manager build path needs Flutter 3.44 / Dart 3.11 (the diff --git a/src/serious_python_linux/linux/python_versions.properties b/src/serious_python_linux/linux/python_versions.properties index b4703e82..e197b9b8 100644 --- a/src/serious_python_linux/linux/python_versions.properties +++ b/src/serious_python_linux/linux/python_versions.properties @@ -1,8 +1,8 @@ # GENERATED by `dart run serious_python:gen_version_tables` from -# python-build manifest.json (release 20260902). Do not edit by hand. +# python-build manifest.json (release 20260908). Do not edit by hand. default_python_version=3.14 -dart_bridge_version=1.8.0 -python_build_release_date=20260902 +dart_bridge_version=1.9.0 +python_build_release_date=20260908 3.12.full_version=3.12.14 3.12.android_abis=arm64-v8a,x86_64,armeabi-v7a 3.13.full_version=3.13.15 diff --git a/src/serious_python_linux/pubspec.yaml b/src/serious_python_linux/pubspec.yaml index 58ab3d72..fee59d33 100644 --- a/src/serious_python_linux/pubspec.yaml +++ b/src/serious_python_linux/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_linux description: Linux implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 4.6.0 +version: 4.7.0 environment: sdk: '>=3.1.3 <4.0.0' diff --git a/src/serious_python_platform_interface/lib/src/dart_bridge_ffi.dart b/src/serious_python_platform_interface/lib/src/dart_bridge_ffi.dart index acef515e..d4d99a5c 100644 --- a/src/serious_python_platform_interface/lib/src/dart_bridge_ffi.dart +++ b/src/serious_python_platform_interface/lib/src/dart_bridge_ffi.dart @@ -70,6 +70,9 @@ typedef _DartBridgeSignalDartSessionNative = Void Function( typedef _DartBridgeSignalDartSessionDart = void Function( int, Pointer>, Pointer); +typedef _SeriousPythonHardExitNative = Void Function(Int32); +typedef _SeriousPythonHardExitDart = void Function(int); + // --------------------------------------------------------------------------- // Library binding // --------------------------------------------------------------------------- @@ -104,6 +107,12 @@ class DartBridge { 'dart_bridge_signal_dart_session', (f) => f.asFunction<_DartBridgeSignalDartSessionDart>(), ); + // dart_bridge >= 1.9.0 export; same soft-lookup rationale as above. + _hardExit = _lookupOrNull<_SeriousPythonHardExitNative, + _SeriousPythonHardExitDart>( + 'serious_python_hard_exit', + (f) => f.asFunction<_SeriousPythonHardExitDart>(), + ); } // Generic helper for soft symbol lookup — returns null if the binary @@ -125,6 +134,7 @@ class DartBridge { late final _DartBridgeEnqueueMessageDart _enqueueMessage; late final _DartBridgeIsPythonInitializedDart? _isPythonInitialized; late final _DartBridgeSignalDartSessionDart? _signalDartSession; + late final _SeriousPythonHardExitDart? _hardExit; static DartBridge? _instance; @@ -220,6 +230,21 @@ class DartBridge { f(portMap.length, labels, ports); }); } + + /// True when the loaded libdart_bridge exports [hardExit] (>= 1.9.0). + /// Callers should branch on this rather than assuming the call terminates. + bool get canHardExit => _hardExit != null; + + /// Terminate the process immediately with [exitCode], skipping `atexit` + /// handlers and C++ static destructors. Does not return, *unless* running + /// against a pre-1.9.0 libdart_bridge, where it is a no-op and the caller + /// must fall back to `dart:io`'s `exit()`. + /// + /// `dart:io`'s `exit()` runs the normal C teardown, which destroys the C++ + /// statics inside every loaded CPython extension module. The interpreter + /// lives on a detached thread that may still be running, so that teardown + /// can fault it. Use this instead wherever the process is going away anyway. + void hardExit(int exitCode) => _hardExit?.call(exitCode); } // --------------------------------------------------------------------------- diff --git a/src/serious_python_platform_interface/pubspec.yaml b/src/serious_python_platform_interface/pubspec.yaml index 168d03fc..788d5207 100644 --- a/src/serious_python_platform_interface/pubspec.yaml +++ b/src/serious_python_platform_interface/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_platform_interface description: A common platform interface for the serious_python plugin. homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 4.6.0 +version: 4.7.0 environment: sdk: ">=3.0.0 <4.0.0" diff --git a/src/serious_python_windows/pubspec.yaml b/src/serious_python_windows/pubspec.yaml index bfbbe719..d163b1ee 100644 --- a/src/serious_python_windows/pubspec.yaml +++ b/src/serious_python_windows/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_windows description: Windows implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 4.6.0 +version: 4.7.0 environment: sdk: '>=3.1.3 <4.0.0' diff --git a/src/serious_python_windows/windows/python_versions.properties b/src/serious_python_windows/windows/python_versions.properties index b4703e82..e197b9b8 100644 --- a/src/serious_python_windows/windows/python_versions.properties +++ b/src/serious_python_windows/windows/python_versions.properties @@ -1,8 +1,8 @@ # GENERATED by `dart run serious_python:gen_version_tables` from -# python-build manifest.json (release 20260902). Do not edit by hand. +# python-build manifest.json (release 20260908). Do not edit by hand. default_python_version=3.14 -dart_bridge_version=1.8.0 -python_build_release_date=20260902 +dart_bridge_version=1.9.0 +python_build_release_date=20260908 3.12.full_version=3.12.14 3.12.android_abis=arm64-v8a,x86_64,armeabi-v7a 3.13.full_version=3.13.15 From ce8f09c639130dd011849757610e9263baccbdc0 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 8 Sep 2026 19:54:50 -0700 Subject: [PATCH 2/2] Add 4.7.0 changelogs for all packages; bump darwin and android native versions Every serious_python_* package gets a 4.7.0 entry, matching the convention that each release is recorded in each package's own changelog. The platform-interface entry carries the substance, since DartBridge.hardExit lives there; the platform packages record the python-build re-pin and note that no CPython or Pyodide versions move. The darwin podspec and the android build.gradle.kts carry their own version declarations alongside the pubspec, and both were still on 4.6.0. --- src/serious_python_android/CHANGELOG.md | 4 ++++ src/serious_python_android/android/build.gradle.kts | 2 +- src/serious_python_darwin/CHANGELOG.md | 5 +++++ .../darwin/serious_python_darwin.podspec | 2 +- src/serious_python_linux/CHANGELOG.md | 4 ++++ src/serious_python_platform_interface/CHANGELOG.md | 5 +++++ src/serious_python_windows/CHANGELOG.md | 4 ++++ 7 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/serious_python_android/CHANGELOG.md b/src/serious_python_android/CHANGELOG.md index 8508095c..0cb14ad6 100644 --- a/src/serious_python_android/CHANGELOG.md +++ b/src/serious_python_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.7.0 + +* Re-pins the bundled python-build snapshot to **20260908** and `dart_bridge` to **1.9.0**, whose `libdart_bridge.so` adds the `serious_python_hard_exit` export behind `DartBridge.hardExit`. No CPython versions change from 4.6.0 - **3.12.14 / 3.13.15 / 3.14.7** are unchanged. + ## 4.6.0 * **The bundled Android runtimes move to CPython 3.12.14 / 3.13.15 / 3.14.7** (from 3.12.13 / 3.13.14 / 3.14.6). All three are security releases: they fix a quadratic-complexity DoS in incremental `html.parser.HTMLParser` parsing ([gh-153030](https://github.com/python/cpython/issues/153030)) and quadratic behaviour in `xml.etree.ElementTree` XPath index predicates ([gh-152674](https://github.com/python/cpython/issues/152674)), among others. 3.13.15 and 3.14.7 still bundle libexpat **2.8.2**; only 3.12.14 carries **2.8.3** with the [CVE-2026-72522](https://github.com/python/cpython/issues/155558) fix — see the `serious_python` 4.6.0 notes. diff --git a/src/serious_python_android/android/build.gradle.kts b/src/serious_python_android/android/build.gradle.kts index da8898bd..11e0138f 100644 --- a/src/serious_python_android/android/build.gradle.kts +++ b/src/serious_python_android/android/build.gradle.kts @@ -21,7 +21,7 @@ buildscript { } group = "com.flet.serious_python_android" -version = "4.6.0" +version = "4.7.0" rootProject.allprojects { repositories { diff --git a/src/serious_python_darwin/CHANGELOG.md b/src/serious_python_darwin/CHANGELOG.md index 569a593b..341a84e4 100644 --- a/src/serious_python_darwin/CHANGELOG.md +++ b/src/serious_python_darwin/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.7.0 + +* Re-pins the bundled python-build snapshot to **20260908** and `dart_bridge` to **1.9.0**, whose `dart_bridge.xcframework` adds the `serious_python_hard_exit` export behind `DartBridge.hardExit`. No CPython or Pyodide versions change from 4.6.0 - **3.12.14 / 3.13.15 / 3.14.7** are unchanged, and the python-build release exists to publish the updated manifest. +* Both-layer XCFramework signing is unchanged from 4.6.0; the runtimes are the same artifacts. + ## 4.6.0 * **iOS/macOS runtimes move to CPython 3.12.14 / 3.13.15 / 3.14.7** (from 3.12.13 / 3.13.14 / 3.14.6). All three are security releases: they fix a quadratic-complexity DoS in incremental `html.parser.HTMLParser` parsing ([gh-153030](https://github.com/python/cpython/issues/153030)) and quadratic behaviour in `xml.etree.ElementTree` XPath index predicates ([gh-152674](https://github.com/python/cpython/issues/152674)), among others. 3.13.15 and 3.14.7 still bundle libexpat **2.8.2**; only 3.12.14 carries **2.8.3** with the [CVE-2026-72522](https://github.com/python/cpython/issues/155558) fix — see the `serious_python` 4.6.0 notes. diff --git a/src/serious_python_darwin/darwin/serious_python_darwin.podspec b/src/serious_python_darwin/darwin/serious_python_darwin.podspec index 650596dd..7e0e0d89 100644 --- a/src/serious_python_darwin/darwin/serious_python_darwin.podspec +++ b/src/serious_python_darwin/darwin/serious_python_darwin.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'serious_python_darwin' - s.version = '4.6.0' + s.version = '4.7.0' s.summary = 'A cross-platform plugin for adding embedded Python runtime to your Flutter apps.' s.description = <<-DESC A cross-platform plugin for adding embedded Python runtime to your Flutter apps. diff --git a/src/serious_python_linux/CHANGELOG.md b/src/serious_python_linux/CHANGELOG.md index 0cff064f..2e9429ba 100644 --- a/src/serious_python_linux/CHANGELOG.md +++ b/src/serious_python_linux/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.7.0 + +* Re-pins the bundled python-build snapshot to **20260908** and `dart_bridge` to **1.9.0**, whose `libdart_bridge.so` adds the `serious_python_hard_exit` export behind `DartBridge.hardExit`. No CPython versions change from 4.6.0 - **3.12.14 / 3.13.15 / 3.14.7** are unchanged. + ## 4.6.0 * **The bundled Linux runtimes move to CPython 3.12.14 / 3.13.15 / 3.14.7** (from 3.12.13 / 3.13.14 / 3.14.6). All three are security releases: they fix a quadratic-complexity DoS in incremental `html.parser.HTMLParser` parsing ([gh-153030](https://github.com/python/cpython/issues/153030)) and quadratic behaviour in `xml.etree.ElementTree` XPath index predicates ([gh-152674](https://github.com/python/cpython/issues/152674)), among others. 3.13.15 and 3.14.7 still bundle libexpat **2.8.2**; only 3.12.14 carries **2.8.3** with the [CVE-2026-72522](https://github.com/python/cpython/issues/155558) fix — see the `serious_python` 4.6.0 notes. diff --git a/src/serious_python_platform_interface/CHANGELOG.md b/src/serious_python_platform_interface/CHANGELOG.md index 5d910075..398a0057 100644 --- a/src/serious_python_platform_interface/CHANGELOG.md +++ b/src/serious_python_platform_interface/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.7.0 + +* **`DartBridge.hardExit(exitCode)` / `DartBridge.canHardExit`**, binding `serious_python_hard_exit` from `dart_bridge` 1.9.0. `dart:io`'s `exit()` runs the normal C teardown, which destroys the C++ statics inside every loaded CPython extension module while the interpreter thread may still be running inside one of them; `hardExit` skips it. The symbol is resolved through the existing soft lookup, so an app built against an older `libdart_bridge` still loads, `canHardExit` is `false`, and the caller falls back to `exit()`. See the `serious_python` 4.7.0 notes. +* Re-pins the bundled python-build snapshot to **20260908** and `dart_bridge` to **1.9.0**. + ## 4.6.0 * Version bump aligning with the `serious_python_*` 4.6.0 release. diff --git a/src/serious_python_windows/CHANGELOG.md b/src/serious_python_windows/CHANGELOG.md index 76f4b809..aef1588f 100644 --- a/src/serious_python_windows/CHANGELOG.md +++ b/src/serious_python_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.7.0 + +* Re-pins the bundled python-build snapshot to **20260908** and `dart_bridge` to **1.9.0**, whose `dart_bridge.dll` adds the `serious_python_hard_exit` export behind `DartBridge.hardExit`. No CPython versions change from 4.6.0 - **3.12.14 / 3.13.15 / 3.14.7** are unchanged. + ## 4.6.0 * **The bundled Windows runtimes move to CPython 3.12.14 / 3.13.15 / 3.14.7** (from 3.12.13 / 3.13.14 / 3.14.6). All three are security releases: they fix a quadratic-complexity DoS in incremental `html.parser.HTMLParser` parsing ([gh-153030](https://github.com/python/cpython/issues/153030)) and quadratic behaviour in `xml.etree.ElementTree` XPath index predicates ([gh-152674](https://github.com/python/cpython/issues/152674)), among others. 3.13.15 and 3.14.7 still bundle libexpat **2.8.2**; only 3.12.14 carries **2.8.3** with the [CVE-2026-72522](https://github.com/python/cpython/issues/155558) fix — see the `serious_python` 4.6.0 notes.