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
stdout;
import 'package:meta/meta.dart';
import 'package:file/file.dart';
import '../globals.dart' as globals;
import 'async_guard.dart';
import 'context.dart';
import 'file_system.dart';
import 'platform.dart';
import 'process.dart';
export 'dart:io'
......@@ -165,16 +164,18 @@ void restoreExitFunction() {
/// [ProcessSignal] instances are available on this class (e.g. "send").
class ProcessSignal {
@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 SIGTERM = _PosixProcessSignal._(io.ProcessSignal.sigterm);
static const ProcessSignal SIGUSR1 = _PosixProcessSignal._(io.ProcessSignal.sigusr1);
static const ProcessSignal SIGUSR2 = _PosixProcessSignal._(io.ProcessSignal.sigusr2);
static const ProcessSignal SIGINT = ProcessSignal(io.ProcessSignal.sigint);
static const ProcessSignal SIGKILL = ProcessSignal(io.ProcessSignal.sigkill);
static const ProcessSignal sigwinch = PosixProcessSignal(io.ProcessSignal.sigwinch);
static const ProcessSignal sigterm = PosixProcessSignal(io.ProcessSignal.sigterm);
static const ProcessSignal sigusr1 = PosixProcessSignal(io.ProcessSignal.sigusr1);
static const ProcessSignal sigusr2 = PosixProcessSignal(io.ProcessSignal.sigusr2);
static const ProcessSignal sigint = ProcessSignal(io.ProcessSignal.sigint);
static const ProcessSignal sigkill = ProcessSignal(io.ProcessSignal.sigkill);
final io.ProcessSignal _delegate;
final Platform _platform;
Stream<ProcessSignal> watch() {
return _delegate.watch().map<ProcessSignal>((io.ProcessSignal signal) => this);
......@@ -184,12 +185,12 @@ class ProcessSignal {
///
/// 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.
///
/// This is implemented by sending the signal using [Process.killPid].
bool send(int pid) {
assert(!globals.platform.isWindows || this == ProcessSignal.SIGTERM);
assert(!_platform.isWindows || this == ProcessSignal.sigterm);
return io.Process.killPid(pid, _delegate);
}
......@@ -200,13 +201,16 @@ class ProcessSignal {
/// A [ProcessSignal] that is only available on Posix platforms.
///
/// 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
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 super.watch();
......@@ -367,10 +371,9 @@ class Stdio {
/// An overridable version of io.ProcessInfo.
abstract class ProcessInfo {
factory ProcessInfo() => _DefaultProcessInfo(globals.fs);
factory ProcessInfo.test(FileSystem fs) => _TestProcessInfo(fs);
factory ProcessInfo(FileSystem fs) => _DefaultProcessInfo(fs);
static ProcessInfo get instance => context.get<ProcessInfo>();
factory ProcessInfo.test(FileSystem fs) => _TestProcessInfo(fs);
int get currentRss;
......@@ -379,8 +382,6 @@ abstract class ProcessInfo {
File writePidFile(String pidFile);
}
ProcessInfo get processInfo => ProcessInfo.instance;
/// The default implementation of [ProcessInfo], which uses [io.ProcessInfo].
class _DefaultProcessInfo implements ProcessInfo {
_DefaultProcessInfo(this._fileSystem);
......
......@@ -24,8 +24,8 @@ abstract class Signals {
// The default list of signals that should cause the process to exit.
static const List<ProcessSignal> defaultExitSignals = <ProcessSignal>[
ProcessSignal.SIGTERM,
ProcessSignal.SIGINT,
ProcessSignal.sigterm,
ProcessSignal.sigint,
];
/// 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.
logger: globals.logger,
terminal: globals.terminal,
signals: globals.signals,
processInfo: processInfo,
processInfo: globals.processInfo,
reportReady: boolArg('report-ready'),
pidFile: stringArg('pid-file'),
)
......
......@@ -67,12 +67,12 @@ class LogsCommand extends FlutterCommand {
);
// When terminating, close down the log reader.
ProcessSignal.SIGINT.watch().listen((ProcessSignal signal) {
ProcessSignal.sigint.watch().listen((ProcessSignal signal) {
subscription.cancel();
globals.printStatus('');
exitCompleter.complete(0);
});
ProcessSignal.SIGTERM.watch().listen((ProcessSignal signal) {
ProcessSignal.sigterm.watch().listen((ProcessSignal signal) {
subscription.cancel();
exitCompleter.complete(0);
});
......
......@@ -12,7 +12,6 @@ import 'package:vm_service/vm_service.dart';
import '../android/android_device.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../device.dart';
......@@ -639,7 +638,7 @@ class RunCommand extends RunCommandBase {
logger: globals.logger,
terminal: globals.terminal,
signals: globals.signals,
processInfo: processInfo,
processInfo: globals.processInfo,
reportReady: boolArg('report-ready'),
pidFile: stringArg('pid-file'),
)
......
......@@ -286,7 +286,7 @@ Future<T> runInContext<T>(
logger: globals.logger,
platform: globals.platform,
),
ProcessInfo: () => ProcessInfo(),
ProcessInfo: () => ProcessInfo(globals.fs),
ProcessManager: () => ErrorHandlingProcessManager(
delegate: const LocalProcessManager(),
platform: globals.platform,
......
......@@ -126,6 +126,8 @@ Future<bool> get isRunningOnBot => botDetector.isRunningOnBot;
/// The current system clock instance.
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
/// fail in some way.
///
......
......@@ -209,7 +209,7 @@ class CommandResultEvent extends UsageEvent {
// so that we can get the command result even if trying to grab maxRss
// throws an exception.
try {
final int maxRss = processInfo.maxRss;
final int maxRss = globals.processInfo.maxRss;
flutterUsage.sendEvent(
'tool-command-max-rss',
category,
......
......@@ -1501,11 +1501,11 @@ class TerminalHandler {
void registerSignalHandlers() {
assert(residentRunner.stayResident);
_addSignalHandler(io.ProcessSignal.SIGINT, _cleanUp);
_addSignalHandler(io.ProcessSignal.SIGTERM, _cleanUp);
_addSignalHandler(io.ProcessSignal.sigint, _cleanUp);
_addSignalHandler(io.ProcessSignal.sigterm, _cleanUp);
if (residentRunner.supportsServiceProtocol && residentRunner.supportsRestart) {
_addSignalHandler(io.ProcessSignal.SIGUSR1, _handleSignal);
_addSignalHandler(io.ProcessSignal.SIGUSR2, _handleSignal);
_addSignalHandler(io.ProcessSignal.sigusr1, _handleSignal);
_addSignalHandler(io.ProcessSignal.sigusr2, _handleSignal);
if (_pidFile != null) {
_logger.printTrace('Writing pid to: $_pidFile');
_actualPidFile = _processInfo.writePidFile(_pidFile);
......@@ -1663,7 +1663,7 @@ class TerminalHandler {
}
_processingUserRequest = true;
final bool fullRestart = signal == io.ProcessSignal.SIGUSR2;
final bool fullRestart = signal == io.ProcessSignal.sigusr2;
try {
await residentRunner.restart(fullRestart: fullRestart);
......
......@@ -1075,8 +1075,8 @@ abstract class FlutterCommand extends Command<void> {
globals.systemClock.now(),
);
}
globals.signals.addHandler(io.ProcessSignal.SIGTERM, handler);
globals.signals.addHandler(io.ProcessSignal.SIGINT, handler);
globals.signals.addHandler(io.ProcessSignal.sigterm, handler);
globals.signals.addHandler(io.ProcessSignal.sigint, handler);
}
/// Logs data about this command.
......
......@@ -9,6 +9,7 @@ import 'dart:io' as io;
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
......@@ -66,7 +67,7 @@ void main() {
});
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', () {
......@@ -100,6 +101,18 @@ void main() {
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 {
......
......@@ -637,7 +637,7 @@ class FakeSignals implements Signals {
@override
Object addHandler(ProcessSignal signal, SignalHandler handler) {
if (signal == ProcessSignal.SIGTERM) {
if (signal == ProcessSignal.sigterm) {
return delegate.addHandler(subForSigTerm, handler);
}
return delegate.addHandler(signal, handler);
......
......@@ -204,7 +204,7 @@ abstract class FlutterTestDriver {
Future<int> _killForcefully() {
_debugPrint('Sending SIGKILL to $_processPid..');
ProcessSignal.SIGKILL.send(_processPid);
ProcessSignal.sigkill.send(_processPid);
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