@@ -11,8 +11,15 @@ import 'gen.dart';
1111export 'gen.dart' ;
1212
1313CPython ? _cpython;
14+ String ? _logcatForwardingError;
1415const _logcatInitScript = r'''
1516import sys, logging
17+
18+ # Make this init idempotent across Dart isolate restarts.
19+ if getattr(sys, "__serious_python_logcat_configured__", False):
20+ raise SystemExit
21+ sys.__serious_python_logcat_configured__ = True
22+
1623from ctypes import cdll
1724liblog = cdll.LoadLibrary("liblog.so")
1825ANDROID_LOG_INFO = 4
@@ -73,19 +80,23 @@ Future<String> runPythonProgramFFI(bool sync, String dynamicLibPath,
7380 final receivePort = ReceivePort ();
7481 if (sync ) {
7582 // sync run
76- return await runPythonProgramInIsolate (
77- [receivePort.sendPort, dynamicLibPath, pythonProgramPath, script]);
83+ try {
84+ return await runPythonProgramInIsolate (
85+ [receivePort.sendPort, dynamicLibPath, pythonProgramPath, script]);
86+ } finally {
87+ receivePort.close ();
88+ }
7889 } else {
79- var completer = Completer <String >();
8090 // async run
81- final isolate = await Isolate .spawn (runPythonProgramInIsolate,
91+ //
92+ // IMPORTANT: do not `isolate.kill()` here. Killing the isolate can abort the
93+ // underlying OS thread while it still interacts with CPython, leaving the
94+ // interpreter/GIL in a bad state for subsequent runs.
95+ await Isolate .spawn (runPythonProgramInIsolate,
8296 [receivePort.sendPort, dynamicLibPath, pythonProgramPath, script]);
83- receivePort.listen ((message) {
84- receivePort.close ();
85- isolate.kill ();
86- completer.complete (message);
87- });
88- return completer.future;
97+ final message = await receivePort.first;
98+ receivePort.close ();
99+ return message as String ;
89100 }
90101}
91102
@@ -146,9 +157,9 @@ Future<String> runPythonProgramInIsolate(List<Object> arguments) async {
146157 return "" ;
147158 });
148159 } finally {
149- // Finalize interpreter so subsequent runs start clean and GIL is free.
150- _finalizeInterpreter (cpython);
151- _cpython = null ;
160+ // Keep interpreter alive between runs. Finalizing + re-initializing the
161+ // interpreter is not reliably supported and has caused native crashes
162+ // (e.g. during _ctypes re-import) on Android.
152163 }
153164
154165 sendPort.send (result);
@@ -208,9 +219,11 @@ String? _setupLogcatForwarding(CPython cpython) {
208219 malloc.free (setupPtr);
209220
210221 if (result != 0 ) {
211- return getPythonError (cpython);
222+ _logcatForwardingError = getPythonError (cpython);
223+ return _logcatForwardingError;
212224 }
213225
214226 _debug ("logcat forwarding configured" );
227+ _logcatForwardingError = null ;
215228 return null ;
216229}
0 commit comments