Unverified Commit 9f420ffb authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] io cleanups to simplify null safety migration (#77955)

parent 85b22ff5
...@@ -48,11 +48,10 @@ import 'dart:io' as io ...@@ -48,11 +48,10 @@ import 'dart:io' as io
stdout; stdout;
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:file/file.dart';
import '../globals.dart' as globals;
import 'async_guard.dart'; import 'async_guard.dart';
import 'context.dart'; import 'platform.dart';
import 'file_system.dart';
import 'process.dart'; import 'process.dart';
export 'dart:io' export 'dart:io'
...@@ -165,16 +164,18 @@ void restoreExitFunction() { ...@@ -165,16 +164,18 @@ void restoreExitFunction() {
/// [ProcessSignal] instances are available on this class (e.g. "send"). /// [ProcessSignal] instances are available on this class (e.g. "send").
class ProcessSignal { class ProcessSignal {
@visibleForTesting @visibleForTesting
const ProcessSignal(this._delegate); const ProcessSignal(this._delegate, {@visibleForTesting Platform platform = const LocalPlatform()})
: _platform = platform;
static const ProcessSignal SIGWINCH = _PosixProcessSignal._(io.ProcessSignal.sigwinch); static const ProcessSignal sigwinch = PosixProcessSignal(io.ProcessSignal.sigwinch);
static const ProcessSignal SIGTERM = _PosixProcessSignal._(io.ProcessSignal.sigterm); static const ProcessSignal sigterm = PosixProcessSignal(io.ProcessSignal.sigterm);
static const ProcessSignal SIGUSR1 = _PosixProcessSignal._(io.ProcessSignal.sigusr1); static const ProcessSignal sigusr1 = PosixProcessSignal(io.ProcessSignal.sigusr1);
static const ProcessSignal SIGUSR2 = _PosixProcessSignal._(io.ProcessSignal.sigusr2); static const ProcessSignal sigusr2 = PosixProcessSignal(io.ProcessSignal.sigusr2);
static const ProcessSignal SIGINT = ProcessSignal(io.ProcessSignal.sigint); static const ProcessSignal sigint = ProcessSignal(io.ProcessSignal.sigint);
static const ProcessSignal SIGKILL = ProcessSignal(io.ProcessSignal.sigkill); static const ProcessSignal sigkill = ProcessSignal(io.ProcessSignal.sigkill);
final io.ProcessSignal _delegate; final io.ProcessSignal _delegate;
final Platform _platform;
Stream<ProcessSignal> watch() { Stream<ProcessSignal> watch() {
return _delegate.watch().map<ProcessSignal>((io.ProcessSignal signal) => this); return _delegate.watch().map<ProcessSignal>((io.ProcessSignal signal) => this);
...@@ -184,12 +185,12 @@ class ProcessSignal { ...@@ -184,12 +185,12 @@ class ProcessSignal {
/// ///
/// Returns true if the signal was delivered, false otherwise. /// Returns true if the signal was delivered, false otherwise.
/// ///
/// On Windows, this can only be used with [ProcessSignal.SIGTERM], which /// On Windows, this can only be used with [ProcessSignal.sigterm], which
/// terminates the process. /// terminates the process.
/// ///
/// This is implemented by sending the signal using [Process.killPid]. /// This is implemented by sending the signal using [Process.killPid].
bool send(int pid) { bool send(int pid) {
assert(!globals.platform.isWindows || this == ProcessSignal.SIGTERM); assert(!_platform.isWindows || this == ProcessSignal.sigterm);
return io.Process.killPid(pid, _delegate); return io.Process.killPid(pid, _delegate);
} }
...@@ -200,13 +201,16 @@ class ProcessSignal { ...@@ -200,13 +201,16 @@ class ProcessSignal {
/// A [ProcessSignal] that is only available on Posix platforms. /// A [ProcessSignal] that is only available on Posix platforms.
/// ///
/// Listening to a [_PosixProcessSignal] is a no-op on Windows. /// Listening to a [_PosixProcessSignal] is a no-op on Windows.
class _PosixProcessSignal extends ProcessSignal { @visibleForTesting
class PosixProcessSignal extends ProcessSignal {
const _PosixProcessSignal._(io.ProcessSignal wrappedSignal) : super(wrappedSignal); const PosixProcessSignal(io.ProcessSignal wrappedSignal, {@visibleForTesting Platform platform = const LocalPlatform()})
: super(wrappedSignal, platform: platform);
@override @override
Stream<ProcessSignal> watch() { Stream<ProcessSignal> watch() {
if (globals.platform.isWindows) { // This uses the real platform since it invokes dart:io functionality directly.
if (_platform.isWindows) {
return const Stream<ProcessSignal>.empty(); return const Stream<ProcessSignal>.empty();
} }
return super.watch(); return super.watch();
...@@ -367,10 +371,9 @@ class Stdio { ...@@ -367,10 +371,9 @@ class Stdio {
/// An overridable version of io.ProcessInfo. /// An overridable version of io.ProcessInfo.
abstract class ProcessInfo { abstract class ProcessInfo {
factory ProcessInfo() => _DefaultProcessInfo(globals.fs); factory ProcessInfo(FileSystem fs) => _DefaultProcessInfo(fs);
factory ProcessInfo.test(FileSystem fs) => _TestProcessInfo(fs);
static ProcessInfo get instance => context.get<ProcessInfo>(); factory ProcessInfo.test(FileSystem fs) => _TestProcessInfo(fs);
int get currentRss; int get currentRss;
...@@ -379,8 +382,6 @@ abstract class ProcessInfo { ...@@ -379,8 +382,6 @@ abstract class ProcessInfo {
File writePidFile(String pidFile); File writePidFile(String pidFile);
} }
ProcessInfo get processInfo => ProcessInfo.instance;
/// The default implementation of [ProcessInfo], which uses [io.ProcessInfo]. /// The default implementation of [ProcessInfo], which uses [io.ProcessInfo].
class _DefaultProcessInfo implements ProcessInfo { class _DefaultProcessInfo implements ProcessInfo {
_DefaultProcessInfo(this._fileSystem); _DefaultProcessInfo(this._fileSystem);
......
...@@ -24,8 +24,8 @@ abstract class Signals { ...@@ -24,8 +24,8 @@ abstract class Signals {
// The default list of signals that should cause the process to exit. // The default list of signals that should cause the process to exit.
static const List<ProcessSignal> defaultExitSignals = <ProcessSignal>[ static const List<ProcessSignal> defaultExitSignals = <ProcessSignal>[
ProcessSignal.SIGTERM, ProcessSignal.sigterm,
ProcessSignal.SIGINT, ProcessSignal.sigint,
]; ];
/// Adds a signal handler to run on receipt of signal. /// Adds a signal handler to run on receipt of signal.
......
...@@ -368,7 +368,7 @@ known, it can be explicitly provided to attach via the command-line, e.g. ...@@ -368,7 +368,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
logger: globals.logger, logger: globals.logger,
terminal: globals.terminal, terminal: globals.terminal,
signals: globals.signals, signals: globals.signals,
processInfo: processInfo, processInfo: globals.processInfo,
reportReady: boolArg('report-ready'), reportReady: boolArg('report-ready'),
pidFile: stringArg('pid-file'), pidFile: stringArg('pid-file'),
) )
......
...@@ -67,12 +67,12 @@ class LogsCommand extends FlutterCommand { ...@@ -67,12 +67,12 @@ class LogsCommand extends FlutterCommand {
); );
// When terminating, close down the log reader. // When terminating, close down the log reader.
ProcessSignal.SIGINT.watch().listen((ProcessSignal signal) { ProcessSignal.sigint.watch().listen((ProcessSignal signal) {
subscription.cancel(); subscription.cancel();
globals.printStatus(''); globals.printStatus('');
exitCompleter.complete(0); exitCompleter.complete(0);
}); });
ProcessSignal.SIGTERM.watch().listen((ProcessSignal signal) { ProcessSignal.sigterm.watch().listen((ProcessSignal signal) {
subscription.cancel(); subscription.cancel();
exitCompleter.complete(0); exitCompleter.complete(0);
}); });
......
...@@ -12,7 +12,6 @@ import 'package:vm_service/vm_service.dart'; ...@@ -12,7 +12,6 @@ import 'package:vm_service/vm_service.dart';
import '../android/android_device.dart'; import '../android/android_device.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/io.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../device.dart'; import '../device.dart';
...@@ -639,7 +638,7 @@ class RunCommand extends RunCommandBase { ...@@ -639,7 +638,7 @@ class RunCommand extends RunCommandBase {
logger: globals.logger, logger: globals.logger,
terminal: globals.terminal, terminal: globals.terminal,
signals: globals.signals, signals: globals.signals,
processInfo: processInfo, processInfo: globals.processInfo,
reportReady: boolArg('report-ready'), reportReady: boolArg('report-ready'),
pidFile: stringArg('pid-file'), pidFile: stringArg('pid-file'),
) )
......
...@@ -286,7 +286,7 @@ Future<T> runInContext<T>( ...@@ -286,7 +286,7 @@ Future<T> runInContext<T>(
logger: globals.logger, logger: globals.logger,
platform: globals.platform, platform: globals.platform,
), ),
ProcessInfo: () => ProcessInfo(), ProcessInfo: () => ProcessInfo(globals.fs),
ProcessManager: () => ErrorHandlingProcessManager( ProcessManager: () => ErrorHandlingProcessManager(
delegate: const LocalProcessManager(), delegate: const LocalProcessManager(),
platform: globals.platform, platform: globals.platform,
......
...@@ -126,6 +126,8 @@ Future<bool> get isRunningOnBot => botDetector.isRunningOnBot; ...@@ -126,6 +126,8 @@ Future<bool> get isRunningOnBot => botDetector.isRunningOnBot;
/// The current system clock instance. /// The current system clock instance.
SystemClock get systemClock => context.get<SystemClock>(); SystemClock get systemClock => context.get<SystemClock>();
ProcessInfo get processInfo => context.get<ProcessInfo>();
/// Display an error level message to the user. Commands should use this if they /// Display an error level message to the user. Commands should use this if they
/// fail in some way. /// fail in some way.
/// ///
......
...@@ -209,7 +209,7 @@ class CommandResultEvent extends UsageEvent { ...@@ -209,7 +209,7 @@ class CommandResultEvent extends UsageEvent {
// so that we can get the command result even if trying to grab maxRss // so that we can get the command result even if trying to grab maxRss
// throws an exception. // throws an exception.
try { try {
final int maxRss = processInfo.maxRss; final int maxRss = globals.processInfo.maxRss;
flutterUsage.sendEvent( flutterUsage.sendEvent(
'tool-command-max-rss', 'tool-command-max-rss',
category, category,
......
...@@ -1501,11 +1501,11 @@ class TerminalHandler { ...@@ -1501,11 +1501,11 @@ class TerminalHandler {
void registerSignalHandlers() { void registerSignalHandlers() {
assert(residentRunner.stayResident); assert(residentRunner.stayResident);
_addSignalHandler(io.ProcessSignal.SIGINT, _cleanUp); _addSignalHandler(io.ProcessSignal.sigint, _cleanUp);
_addSignalHandler(io.ProcessSignal.SIGTERM, _cleanUp); _addSignalHandler(io.ProcessSignal.sigterm, _cleanUp);
if (residentRunner.supportsServiceProtocol && residentRunner.supportsRestart) { if (residentRunner.supportsServiceProtocol && residentRunner.supportsRestart) {
_addSignalHandler(io.ProcessSignal.SIGUSR1, _handleSignal); _addSignalHandler(io.ProcessSignal.sigusr1, _handleSignal);
_addSignalHandler(io.ProcessSignal.SIGUSR2, _handleSignal); _addSignalHandler(io.ProcessSignal.sigusr2, _handleSignal);
if (_pidFile != null) { if (_pidFile != null) {
_logger.printTrace('Writing pid to: $_pidFile'); _logger.printTrace('Writing pid to: $_pidFile');
_actualPidFile = _processInfo.writePidFile(_pidFile); _actualPidFile = _processInfo.writePidFile(_pidFile);
...@@ -1663,7 +1663,7 @@ class TerminalHandler { ...@@ -1663,7 +1663,7 @@ class TerminalHandler {
} }
_processingUserRequest = true; _processingUserRequest = true;
final bool fullRestart = signal == io.ProcessSignal.SIGUSR2; final bool fullRestart = signal == io.ProcessSignal.sigusr2;
try { try {
await residentRunner.restart(fullRestart: fullRestart); await residentRunner.restart(fullRestart: fullRestart);
......
...@@ -1075,8 +1075,8 @@ abstract class FlutterCommand extends Command<void> { ...@@ -1075,8 +1075,8 @@ abstract class FlutterCommand extends Command<void> {
globals.systemClock.now(), globals.systemClock.now(),
); );
} }
globals.signals.addHandler(io.ProcessSignal.SIGTERM, handler); globals.signals.addHandler(io.ProcessSignal.sigterm, handler);
globals.signals.addHandler(io.ProcessSignal.SIGINT, handler); globals.signals.addHandler(io.ProcessSignal.sigint, handler);
} }
/// Logs data about this command. /// Logs data about this command.
......
...@@ -9,6 +9,7 @@ import 'dart:io' as io; ...@@ -9,6 +9,7 @@ import 'dart:io' as io;
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:test/fake.dart'; import 'package:test/fake.dart';
import '../../src/common.dart'; import '../../src/common.dart';
...@@ -66,7 +67,7 @@ void main() { ...@@ -66,7 +67,7 @@ void main() {
}); });
testUsingContext('ProcessSignal toString() works', () async { testUsingContext('ProcessSignal toString() works', () async {
expect(io.ProcessSignal.sigint.toString(), ProcessSignal.SIGINT.toString()); expect(io.ProcessSignal.sigint.toString(), ProcessSignal.sigint.toString());
}); });
test('exit throws a StateError if called without being overriden', () { test('exit throws a StateError if called without being overriden', () {
...@@ -100,6 +101,18 @@ void main() { ...@@ -100,6 +101,18 @@ void main() {
resetNetworkInterfaceLister(); resetNetworkInterfaceLister();
}); });
testWithoutContext('Does not listen to Posix process signals on windows', () async {
final FakePlatform windows = FakePlatform(operatingSystem: 'windows');
final FakePlatform linux = FakePlatform(operatingSystem: 'linux');
final FakeProcessSignal fakeSignalA = FakeProcessSignal();
final FakeProcessSignal fakeSignalB = FakeProcessSignal();
fakeSignalA.controller.add(fakeSignalA);
fakeSignalB.controller.add(fakeSignalB);
expect(await PosixProcessSignal(fakeSignalA, platform: windows).watch().isEmpty, true);
expect(await PosixProcessSignal(fakeSignalB, platform: linux).watch().first, isNotNull);
});
} }
class FakeProcessSignal extends Fake implements io.ProcessSignal { class FakeProcessSignal extends Fake implements io.ProcessSignal {
......
...@@ -637,7 +637,7 @@ class FakeSignals implements Signals { ...@@ -637,7 +637,7 @@ class FakeSignals implements Signals {
@override @override
Object addHandler(ProcessSignal signal, SignalHandler handler) { Object addHandler(ProcessSignal signal, SignalHandler handler) {
if (signal == ProcessSignal.SIGTERM) { if (signal == ProcessSignal.sigterm) {
return delegate.addHandler(subForSigTerm, handler); return delegate.addHandler(subForSigTerm, handler);
} }
return delegate.addHandler(signal, handler); return delegate.addHandler(signal, handler);
......
...@@ -204,7 +204,7 @@ abstract class FlutterTestDriver { ...@@ -204,7 +204,7 @@ abstract class FlutterTestDriver {
Future<int> _killForcefully() { Future<int> _killForcefully() {
_debugPrint('Sending SIGKILL to $_processPid..'); _debugPrint('Sending SIGKILL to $_processPid..');
ProcessSignal.SIGKILL.send(_processPid); ProcessSignal.sigkill.send(_processPid);
return _process.exitCode; return _process.exitCode;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment