@@ -34,9 +34,6 @@ final class MwebdService {
3434
3535 final Mutex _torConnectingLock = Mutex ();
3636
37- // Track active log stream controllers for cleanup during shutdown.
38- final Set <StreamController <String >> _activeLogControllers = {};
39-
4037 static final instance = MwebdService ._();
4138
4239 MwebdService ._() {
@@ -207,9 +204,6 @@ final class MwebdService {
207204 String leftover = '' ;
208205 Timer ? timer;
209206
210- // Track this controller for cleanup during shutdown.
211- _activeLogControllers.add (controller);
212-
213207 final path =
214208 "${(await StackFileSystem .applicationMwebdDirectory (net == CryptoCurrencyNetwork .main ? "mainnet" : "testnet" )).path }"
215209 "${Platform .pathSeparator }logs"
@@ -243,141 +237,11 @@ final class MwebdService {
243237
244238 controller.onCancel = () {
245239 timer? .cancel ();
246- _activeLogControllers.remove (controller);
247240 controller.close ();
248241 };
249242
250243 return controller.stream;
251244 }
252-
253- /// Shutdown all mwebd servers and clean up resources.
254- ///
255- /// This method should be called when the app is terminating to prevent hanging.
256- Future <void > shutdown () async {
257- final stopwatch = Stopwatch ()..start ();
258- Logging .instance.i ("MwebdService shutdown() started" );
259-
260- await _updateLock.protect (() async {
261- // Cancel stream subscriptions to prevent further events.
262- try {
263- await _torStatusListener.cancel ();
264- Logging .instance.i ("Canceled tor status listener" );
265- } catch (e, s) {
266- Logging .instance.w (
267- "Error canceling tor status listener" ,
268- error: e,
269- stackTrace: s,
270- );
271- }
272-
273- try {
274- await _torPreferenceListener.cancel ();
275- Logging .instance.i ("Canceled tor preference listener" );
276- } catch (e, s) {
277- Logging .instance.w (
278- "Error canceling tor preference listener" ,
279- error: e,
280- stackTrace: s,
281- );
282- }
283-
284- // Cancel all active log stream controllers and their timers.
285- final logControllers = List .from (_activeLogControllers);
286- for (final controller in logControllers) {
287- try {
288- await controller.close ();
289- Logging .instance.i ("Closed log stream controller" );
290- } catch (e, s) {
291- Logging .instance.w (
292- "Error closing log stream controller" ,
293- error: e,
294- stackTrace: s,
295- );
296- }
297- }
298- _activeLogControllers.clear ();
299-
300- // Stop all servers and clean up clients with timeout protection.
301- final stopFutures = < Future > [];
302- for (final entry in _map.values) {
303- stopFutures.add (_shutdownServerSafely (entry));
304- }
305-
306- // Wait for all shutdowns with overall timeout.
307- try {
308- await Future .wait (stopFutures).timeout (
309- const Duration (seconds: 10 ),
310- onTimeout: () {
311- Logging .instance.w ("Timeout waiting for mwebd servers to stop" );
312- return []; // Return a dummy list.
313- },
314- );
315- } catch (e, s) {
316- Logging .instance.w (
317- "Error during mwebd servers shutdown" ,
318- error: e,
319- stackTrace: s,
320- );
321- }
322-
323- _map.clear ();
324-
325- final elapsedMs = stopwatch.elapsedMilliseconds;
326- Logging .instance.i ("MwebdService shutdown() completed in ${elapsedMs }ms" );
327-
328- // Warn if shutdown took too long (could indicate hanging).
329- if (elapsedMs > 3000 ) {
330- Logging .instance.w ("MwebdService shutdown took ${elapsedMs }ms - longer than expected" );
331- }
332- });
333- }
334-
335- /// Safely shutdown a server/client pair with timeout protection.
336- Future <void > _shutdownServerSafely (
337- ({MwebdServer server, MwebClient client}) entry,
338- ) async {
339- final serverStopwatch = Stopwatch ()..start ();
340- Logging .instance.i ("Starting shutdown of mwebd server/client pair" );
341-
342- try {
343- // Clean up client first.
344- final clientStopwatch = Stopwatch ()..start ();
345- await entry.client.cleanup ().timeout (
346- const Duration (seconds: 3 ),
347- onTimeout: () {
348- Logging .instance.w ("Timeout cleaning up mweb client after 3s" );
349- },
350- );
351- Logging .instance.i ("Client cleanup completed in ${clientStopwatch .elapsedMilliseconds }ms" );
352- } catch (e, s) {
353- Logging .instance.w (
354- "Error cleaning up mweb client" ,
355- error: e,
356- stackTrace: s,
357- );
358- }
359-
360- try {
361- // Stop server with timeout protection.
362- final serverShutdownStopwatch = Stopwatch ()..start ();
363- await entry.server.stopServer ().timeout (
364- const Duration (seconds: 5 ),
365- onTimeout: () {
366- Logging .instance.w ("Timeout stopping mwebd server after 5s" );
367- },
368- );
369- Logging .instance.i ("Server stop completed in ${serverShutdownStopwatch .elapsedMilliseconds }ms" );
370- } catch (e, s) {
371- Logging .instance.w (
372- "Error stopping mwebd server" ,
373- error: e,
374- stackTrace: s,
375- );
376- }
377-
378- final totalMs = serverStopwatch.elapsedMilliseconds;
379- Logging .instance.i ("Server/client pair shutdown completed in ${totalMs }ms" );
380- }
381245}
382246
383247// ============================================================================
0 commit comments