Unverified Commit fffb7630 authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Give file system recording serialization a timeout. (#15217)

Some file I/O is piped from OS processes and never completes,
so without havign a timeout on the recording serialzation, we
end up waiting forever on that I/O to complete.
parent f3c806c9
...@@ -7,7 +7,6 @@ import 'package:file/local.dart'; ...@@ -7,7 +7,6 @@ import 'package:file/local.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:file/record_replay.dart'; import 'package:file/record_replay.dart';
import 'common.dart' show throwToolExit; import 'common.dart' show throwToolExit;
import 'context.dart'; import 'context.dart';
import 'platform.dart'; import 'platform.dart';
...@@ -40,7 +39,9 @@ void enableRecordingFileSystem(String location) { ...@@ -40,7 +39,9 @@ void enableRecordingFileSystem(String location) {
final RecordingFileSystem fileSystem = new RecordingFileSystem( final RecordingFileSystem fileSystem = new RecordingFileSystem(
delegate: _kLocalFs, destination: dir); delegate: _kLocalFs, destination: dir);
addShutdownHook(() async { addShutdownHook(() async {
await fileSystem.recording.flush(); await fileSystem.recording.flush(
pendingResultTimeout: const Duration(seconds: 5),
);
context.setVariable(FileSystem, originalFileSystem); context.setVariable(FileSystem, originalFileSystem);
}, ShutdownStage.SERIALIZE_RECORDING); }, ShutdownStage.SERIALIZE_RECORDING);
context.setVariable(FileSystem, fileSystem); context.setVariable(FileSystem, fileSystem);
......
...@@ -26,10 +26,10 @@ typedef Future<dynamic> ShutdownHook(); ...@@ -26,10 +26,10 @@ typedef Future<dynamic> ShutdownHook();
/// a given stage will be started in parallel and will be guaranteed to run to /// a given stage will be started in parallel and will be guaranteed to run to
/// completion before shutdown hooks in the next stage are started. /// completion before shutdown hooks in the next stage are started.
class ShutdownStage implements Comparable<ShutdownStage> { class ShutdownStage implements Comparable<ShutdownStage> {
const ShutdownStage._(this._priority); const ShutdownStage._(this.priority);
/// The stage priority. Smaller values will be run before larger values. /// The stage priority. Smaller values will be run before larger values.
final int _priority; final int priority;
/// The stage before the invocation recording (if one exists) is serialized /// The stage before the invocation recording (if one exists) is serialized
/// to disk. Tasks performed during this stage *will* be recorded. /// to disk. Tasks performed during this stage *will* be recorded.
...@@ -48,7 +48,7 @@ class ShutdownStage implements Comparable<ShutdownStage> { ...@@ -48,7 +48,7 @@ class ShutdownStage implements Comparable<ShutdownStage> {
static const ShutdownStage CLEANUP = const ShutdownStage._(4); static const ShutdownStage CLEANUP = const ShutdownStage._(4);
@override @override
int compareTo(ShutdownStage other) => _priority.compareTo(other._priority); int compareTo(ShutdownStage other) => priority.compareTo(other.priority);
} }
Map<ShutdownStage, List<ShutdownHook>> _shutdownHooks = <ShutdownStage, List<ShutdownHook>>{}; Map<ShutdownStage, List<ShutdownHook>> _shutdownHooks = <ShutdownStage, List<ShutdownHook>>{};
...@@ -75,9 +75,11 @@ void addShutdownHook( ...@@ -75,9 +75,11 @@ void addShutdownHook(
/// guaranteed to run to completion before shutdown hooks in the next stage are /// guaranteed to run to completion before shutdown hooks in the next stage are
/// started. /// started.
Future<Null> runShutdownHooks() async { Future<Null> runShutdownHooks() async {
printTrace('Running shutdown hooks');
_shutdownHooksRunning = true; _shutdownHooksRunning = true;
try { try {
for (ShutdownStage stage in _shutdownHooks.keys.toList()..sort()) { for (ShutdownStage stage in _shutdownHooks.keys.toList()..sort()) {
printTrace('Shutdown hook priority ${stage.priority}');
final List<ShutdownHook> hooks = _shutdownHooks.remove(stage); final List<ShutdownHook> hooks = _shutdownHooks.remove(stage);
final List<Future<dynamic>> futures = <Future<dynamic>>[]; final List<Future<dynamic>> futures = <Future<dynamic>>[];
for (ShutdownHook shutdownHook in hooks) for (ShutdownHook shutdownHook in hooks)
...@@ -88,6 +90,7 @@ Future<Null> runShutdownHooks() async { ...@@ -88,6 +90,7 @@ Future<Null> runShutdownHooks() async {
_shutdownHooksRunning = false; _shutdownHooksRunning = false;
} }
assert(_shutdownHooks.isEmpty); assert(_shutdownHooks.isEmpty);
printTrace('Shutdown hooks complete');
} }
Map<String, String> _environment(bool allowReentrantFlutter, [Map<String, String> environment]) { Map<String, String> _environment(bool allowReentrantFlutter, [Map<String, String> environment]) {
......
...@@ -5,9 +5,11 @@ ...@@ -5,9 +5,11 @@
import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/base/process.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import '../src/context.dart';
void main() { void main() {
group('shutdownHooks', () { group('shutdownHooks', () {
test('runInExpectedOrder', () async { testUsingContext('runInExpectedOrder', () async {
int i = 1; int i = 1;
int serializeRecording1; int serializeRecording1;
int serializeRecording2; int serializeRecording2;
......
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