mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-22 04:31:57 +00:00
improve isolate lifecycle and add timeouts
- Add StreamSubscription to manage ReceivePort listener lifecycle - Introduce handshake timeout when waiting for isolate SendPort to prevent hangs - Add response timeout in get<T>() to avoid indefinitely waiting for isolate replies - Replace direct ReceivePort.listen with tracked subscription for safer cleanup - Improve error handling for invalid or missing isolate responses - Strengthen isolate startup reliability and shutdown consistency
This commit is contained in:
parent
8444e308ad
commit
09684a2641
1 changed files with 22 additions and 3 deletions
|
|
@ -21,6 +21,7 @@ class GetIsolateService {
|
||||||
bool _isRunning = false;
|
bool _isRunning = false;
|
||||||
Isolate? _getIsolateService;
|
Isolate? _getIsolateService;
|
||||||
ReceivePort? _receivePort;
|
ReceivePort? _receivePort;
|
||||||
|
StreamSubscription? _receiveSub;
|
||||||
SendPort? _sendPort;
|
SendPort? _sendPort;
|
||||||
|
|
||||||
Future<void> start() async {
|
Future<void> start() async {
|
||||||
|
|
@ -47,7 +48,7 @@ class GetIsolateService {
|
||||||
);
|
);
|
||||||
|
|
||||||
final completer = Completer<SendPort>();
|
final completer = Completer<SendPort>();
|
||||||
_receivePort!.listen((message) {
|
_receiveSub = _receivePort!.listen((message) {
|
||||||
if (message is SendPort) {
|
if (message is SendPort) {
|
||||||
completer.complete(message);
|
completer.complete(message);
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +67,10 @@ class GetIsolateService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_sendPort = await completer.future;
|
_sendPort = await completer.future.timeout(
|
||||||
|
const Duration(seconds: 5),
|
||||||
|
onTimeout: () => throw StateError('Isolate handshake timed out'),
|
||||||
|
);
|
||||||
_isRunning = true;
|
_isRunning = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,8 +179,19 @@ class GetIsolateService {
|
||||||
|
|
||||||
final responsePort = ReceivePort();
|
final responsePort = ReceivePort();
|
||||||
final completer = Completer<T>();
|
final completer = Completer<T>();
|
||||||
|
late final StreamSubscription sub;
|
||||||
|
|
||||||
responsePort.listen((response) {
|
// Timeout safeguard
|
||||||
|
final timer = Timer(const Duration(seconds: 10), () {
|
||||||
|
if (!completer.isCompleted) {
|
||||||
|
sub.cancel();
|
||||||
|
responsePort.close();
|
||||||
|
completer.completeError('Isolate response timeout');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sub = responsePort.listen((response) {
|
||||||
|
timer.cancel();
|
||||||
|
sub.cancel();
|
||||||
responsePort.close();
|
responsePort.close();
|
||||||
if (response is Map<String, dynamic>) {
|
if (response is Map<String, dynamic>) {
|
||||||
if (response['success'] == true) {
|
if (response['success'] == true) {
|
||||||
|
|
@ -184,6 +199,8 @@ class GetIsolateService {
|
||||||
} else {
|
} else {
|
||||||
completer.completeError(response['error']);
|
completer.completeError(response['error']);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
completer.completeError('Invalid isolate response: $response');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -210,7 +227,9 @@ class GetIsolateService {
|
||||||
|
|
||||||
_sendPort?.send('dispose');
|
_sendPort?.send('dispose');
|
||||||
_getIsolateService?.kill(priority: Isolate.immediate);
|
_getIsolateService?.kill(priority: Isolate.immediate);
|
||||||
|
await _receiveSub?.cancel();
|
||||||
_receivePort?.close();
|
_receivePort?.close();
|
||||||
|
_receiveSub = null;
|
||||||
_sendPort = null;
|
_sendPort = null;
|
||||||
_getIsolateService = null;
|
_getIsolateService = null;
|
||||||
_receivePort = null;
|
_receivePort = null;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue