| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| import 'dart:io' as io; |
| |
| /// A wrapper around an [io.Process] class that adds some convenience methods. |
| class ProcessWrapper implements io.Process { |
| /// Constructs a [ProcessWrapper] object that delegates to the specified |
| /// underlying object. |
| ProcessWrapper(this._delegate) |
| : _stdout = StreamController<List<int>>(), |
| _stderr = StreamController<List<int>>(), |
| _stdoutDone = Completer<void>(), |
| _stderrDone = Completer<void>() { |
| _monitorStdioStream(_delegate.stdout, _stdout, _stdoutDone); |
| _monitorStdioStream(_delegate.stderr, _stderr, _stderrDone); |
| } |
| |
| final io.Process _delegate; |
| final StreamController<List<int>> _stdout; |
| final StreamController<List<int>> _stderr; |
| final Completer<void> _stdoutDone; |
| final Completer<void> _stderrDone; |
| |
| /// Listens to the specified [stream], repeating events on it via |
| /// [controller], and completing [completer] once the stream is done. |
| void _monitorStdioStream( |
| Stream<List<int>> stream, |
| StreamController<List<int>> controller, |
| Completer<void> completer, |
| ) { |
| stream.listen( |
| controller.add, |
| onError: controller.addError, |
| onDone: () { |
| controller.close(); |
| completer.complete(); |
| }, |
| ); |
| } |
| |
| @override |
| Future<int> get exitCode => _delegate.exitCode; |
| |
| /// A [Future] that completes when the process has exited and its standard |
| /// output and error streams have closed. |
| /// |
| /// This exists as an alternative to [exitCode], which does not guarantee |
| /// that the stdio streams have closed (it is possible for the exit code to |
| /// be available before stdout and stderr have closed). |
| /// |
| /// The future returned here will complete with the exit code of the process. |
| Future<int> get done async { |
| late int result; |
| await Future.wait<void>(<Future<void>>[ |
| _stdoutDone.future, |
| _stderrDone.future, |
| _delegate.exitCode.then((int value) { |
| result = value; |
| }), |
| ]); |
| return result; |
| } |
| |
| @override |
| bool kill([io.ProcessSignal signal = io.ProcessSignal.sigterm]) { |
| return _delegate.kill(signal); |
| } |
| |
| @override |
| int get pid => _delegate.pid; |
| |
| @override |
| io.IOSink get stdin => _delegate.stdin; |
| |
| @override |
| Stream<List<int>> get stdout => _stdout.stream; |
| |
| @override |
| Stream<List<int>> get stderr => _stderr.stream; |
| } |