Skip to content

Commit 72432c3

Browse files
Reverts "[tool] Guard process writes to frontend server in ResidentCompiler (#152358)" (#153028)
Reverts: flutter/flutter#152358 Initiated by: zanderso Reason for reverting: Speculative revert to determine whether this PR is related to flutter/flutter#153026 Original PR Author: andrewkolos Reviewed By: {christopherfujino} This change reverts the following previous change: Contributes to fixing flutter/flutter#137184. Cleaned up version of earlier PR, flutter/flutter#152187. This PR guards all the writes to `Process::stdin` by wrapping them with `ProcessUtils.writelnToStdinUnsafe`. This way, if any writes fail, we should at least get a stacktrace in our crash reporting.
1 parent e0c051f commit 72432c3

14 files changed

+71
-121
lines changed

packages/flutter_tools/lib/src/base/process.dart

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,8 @@ abstract class ProcessUtils {
228228

229229
/// Write [line] to [stdin] and catch any errors with [onError].
230230
///
231-
/// Concurrent calls to this method will result in an exception due to its
232-
/// dependence on [IOSink.flush] (see https://github.com/dart-lang/sdk/issues/25277).
233-
///
234-
/// Context: specifically with [Process] file descriptors, an exception that
235-
/// is thrown as part of a write can be most reliably caught with a
231+
/// Specifically with [Process] file descriptors, an exception that is
232+
/// thrown as part of a write can be most reliably caught with a
236233
/// [ZoneSpecification] error handler.
237234
///
238235
/// On some platforms, the following code appears to work:
@@ -281,10 +278,6 @@ abstract class ProcessUtils {
281278
);
282279
}
283280

284-
/// See [writelnToStdinGuarded].
285-
///
286-
/// In the event that the write or flush fails, this will throw an exception
287-
/// that preserves the stack trace of the callsite.
288281
static Future<void> writelnToStdinUnsafe({
289282
required IOSink stdin,
290283
required String line,
@@ -296,10 +289,6 @@ abstract class ProcessUtils {
296289
);
297290
}
298291

299-
/// See [writeToStdinGuarded].
300-
///
301-
/// In the event that the write or flush fails, this will throw an exception
302-
/// that preserves the stack trace of the callsite.
303292
static Future<void> writeToStdinUnsafe({
304293
required IOSink stdin,
305294
required String content,

packages/flutter_tools/lib/src/compile.dart

Lines changed: 50 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import 'dart:typed_data';
77

88
import 'package:meta/meta.dart';
99
import 'package:package_config/package_config.dart';
10-
import 'package:pool/pool.dart';
1110
import 'package:process/process.dart';
1211
import 'package:usage/uuid/uuid.dart';
1312

@@ -17,7 +16,6 @@ import 'base/file_system.dart';
1716
import 'base/io.dart';
1817
import 'base/logger.dart';
1918
import 'base/platform.dart';
20-
import 'base/process.dart';
2119
import 'build_info.dart';
2220
import 'convert.dart';
2321

@@ -591,7 +589,7 @@ abstract class ResidentCompiler {
591589
/// Should be invoked when results of compilation are accepted by the client.
592590
///
593591
/// Either [accept] or [reject] should be called after every [recompile] call.
594-
Future<void> accept();
592+
void accept();
595593

596594
/// Should be invoked when results of compilation are rejected by the client.
597595
///
@@ -601,7 +599,7 @@ abstract class ResidentCompiler {
601599
/// Should be invoked when frontend server compiler should forget what was
602600
/// accepted previously so that next call to [recompile] produces complete
603601
/// kernel file.
604-
Future<void> reset();
602+
void reset();
605603

606604
Future<Object> shutdown();
607605
}
@@ -744,9 +742,11 @@ class DefaultResidentCompiler implements ResidentCompiler {
744742
final String inputKey = Uuid().generateV4();
745743

746744
if (nativeAssets != null && nativeAssets.isNotEmpty) {
747-
await _writelnToServerStdin('native-assets $nativeAssets', printTrace: true);
745+
server.stdin.writeln('native-assets $nativeAssets');
746+
_logger.printTrace('<- native-assets $nativeAssets');
748747
}
749-
await _writelnToServerStdin('recompile $mainUri $inputKey', printTrace: true);
748+
server.stdin.writeln('recompile $mainUri $inputKey');
749+
_logger.printTrace('<- recompile $mainUri $inputKey');
750750
final List<Uri>? invalidatedFiles = request.invalidatedFiles;
751751
if (invalidatedFiles != null) {
752752
for (final Uri fileUri in invalidatedFiles) {
@@ -761,7 +761,8 @@ class DefaultResidentCompiler implements ResidentCompiler {
761761
_logger.printTrace(message);
762762
}
763763
}
764-
await _writelnToServerStdin(inputKey, printTrace: true);
764+
server.stdin.writeln(inputKey);
765+
_logger.printTrace('<- $inputKey');
765766

766767
return _stdoutHandler.compilerOutput?.future;
767768
}
@@ -898,10 +899,12 @@ class DefaultResidentCompiler implements ResidentCompiler {
898899
}));
899900

900901
if (nativeAssetsUri != null && nativeAssetsUri.isNotEmpty) {
901-
await _writelnToServerStdin('native assets $nativeAssetsUri', printTrace: true);
902+
_server?.stdin.writeln('native-assets $nativeAssetsUri');
903+
_logger.printTrace('<- native-assets $nativeAssetsUri');
902904
}
903905

904-
await _writelnToServerStdin('compile $scriptUri', printTrace: true);
906+
_server?.stdin.writeln('compile $scriptUri');
907+
_logger.printTrace('<- compile $scriptUri');
905908

906909
return _stdoutHandler.compilerOutput?.future;
907910
}
@@ -942,24 +945,24 @@ class DefaultResidentCompiler implements ResidentCompiler {
942945
}
943946

944947
final String inputKey = Uuid().generateV4();
945-
await _writelnToServerStdinAll(<String>[
946-
'compile-expression $inputKey',
947-
request.expression,
948-
...?request.definitions,
949-
inputKey,
950-
...?request.definitionTypes,
951-
inputKey,
952-
...?request.typeDefinitions,
953-
inputKey,
954-
...?request.typeBounds,
955-
inputKey,
956-
...?request.typeDefaults,
957-
inputKey,
958-
request.libraryUri ?? '',
959-
request.klass ?? '',
960-
request.method ?? '',
961-
request.isStatic.toString(),
962-
]);
948+
server.stdin
949+
..writeln('compile-expression $inputKey')
950+
..writeln(request.expression);
951+
request.definitions?.forEach(server.stdin.writeln);
952+
server.stdin.writeln(inputKey);
953+
request.definitionTypes?.forEach(server.stdin.writeln);
954+
server.stdin.writeln(inputKey);
955+
request.typeDefinitions?.forEach(server.stdin.writeln);
956+
server.stdin.writeln(inputKey);
957+
request.typeBounds?.forEach(server.stdin.writeln);
958+
server.stdin.writeln(inputKey);
959+
request.typeDefaults?.forEach(server.stdin.writeln);
960+
server.stdin
961+
..writeln(inputKey)
962+
..writeln(request.libraryUri ?? '')
963+
..writeln(request.klass ?? '')
964+
..writeln(request.method ?? '')
965+
..writeln(request.isStatic);
963966

964967
return _stdoutHandler.compilerOutput?.future;
965968
}
@@ -997,28 +1000,27 @@ class DefaultResidentCompiler implements ResidentCompiler {
9971000
}
9981001

9991002
final String inputKey = Uuid().generateV4();
1000-
await _writelnToServerStdinAll(<String>[
1001-
'compile-expression-to-js $inputKey',
1002-
request.libraryUri ?? '',
1003-
request.line.toString(),
1004-
request.column.toString(),
1005-
for (final MapEntry<String, String> entry in request.jsModules?.entries ?? <MapEntry<String, String>>[])
1006-
'${entry.key}:${entry.value}',
1007-
inputKey,
1008-
for (final MapEntry<String, String> entry in request.jsFrameValues?.entries ?? <MapEntry<String, String>>[])
1009-
'${entry.key}:${entry.value}',
1010-
inputKey,
1011-
request.moduleName ?? '',
1012-
request.expression ?? ''
1013-
]);
1003+
server.stdin
1004+
..writeln('compile-expression-to-js $inputKey')
1005+
..writeln(request.libraryUri ?? '')
1006+
..writeln(request.line)
1007+
..writeln(request.column);
1008+
request.jsModules?.forEach((String k, String v) { server.stdin.writeln('$k:$v'); });
1009+
server.stdin.writeln(inputKey);
1010+
request.jsFrameValues?.forEach((String k, String v) { server.stdin.writeln('$k:$v'); });
1011+
server.stdin
1012+
..writeln(inputKey)
1013+
..writeln(request.moduleName ?? '')
1014+
..writeln(request.expression ?? '');
10141015

10151016
return _stdoutHandler.compilerOutput?.future;
10161017
}
10171018

10181019
@override
1019-
Future<void> accept() async {
1020+
void accept() {
10201021
if (_compileRequestNeedsConfirmation) {
1021-
await _writelnToServerStdin('accept', printTrace: true);
1022+
_server?.stdin.writeln('accept');
1023+
_logger.printTrace('<- accept');
10221024
}
10231025
_compileRequestNeedsConfirmation = false;
10241026
}
@@ -1039,14 +1041,16 @@ class DefaultResidentCompiler implements ResidentCompiler {
10391041
return Future<CompilerOutput?>.value();
10401042
}
10411043
_stdoutHandler.reset(expectSources: false);
1042-
await _writelnToServerStdin('reject', printTrace: true);
1044+
_server?.stdin.writeln('reject');
1045+
_logger.printTrace('<- reject');
10431046
_compileRequestNeedsConfirmation = false;
10441047
return _stdoutHandler.compilerOutput?.future;
10451048
}
10461049

10471050
@override
1048-
Future<void> reset() async {
1049-
await _writelnToServerStdin('reset', printTrace: true);
1051+
void reset() {
1052+
_server?.stdin.writeln('reset');
1053+
_logger.printTrace('<- reset');
10501054
}
10511055

10521056
@override
@@ -1060,43 +1064,6 @@ class DefaultResidentCompiler implements ResidentCompiler {
10601064
server.kill();
10611065
return server.exitCode;
10621066
}
1063-
1064-
Future<void> _writelnToServerStdin(String line, {
1065-
bool printTrace = false,
1066-
}) async {
1067-
await _writelnToServerStdinAll(<String>[line], printTrace: printTrace);
1068-
}
1069-
1070-
// TODO(andrewkolos): Concurrent calls to ProcessUtils.writelnToStdinUnsafe
1071-
// against the same stdin will result in an exception. To guard against this,
1072-
// we need to force calls to run serially. Ideally, this wouldn't be
1073-
// necessary since we shouldn't have multiple concurrent writes to the
1074-
// compiler process.
1075-
// However, we do. See https://github.com/flutter/flutter/issues/152577.
1076-
final Pool _serverStdinWritePool = Pool(1);
1077-
Future<void> _writelnToServerStdinAll(List<String> lines, {
1078-
bool printTrace = false,
1079-
}) async {
1080-
final Process? server = _server;
1081-
if (server == null) {
1082-
return;
1083-
}
1084-
final PoolResource request = await _serverStdinWritePool.request();
1085-
try {
1086-
await ProcessUtils.writelnToStdinUnsafe(
1087-
stdin: server.stdin,
1088-
line: lines.join('\n'),
1089-
);
1090-
1091-
for (final String line in lines) {
1092-
if (printTrace) {
1093-
_logger.printTrace('<- $line');
1094-
}
1095-
}
1096-
} finally {
1097-
request.release();
1098-
}
1099-
}
11001067
}
11011068

11021069
/// Convert a file URI into a multi-root scheme URI if provided, otherwise

packages/flutter_tools/lib/src/devfs.dart

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ class DevFS {
585585
bool assetBuildFailed = false;
586586
int syncedBytes = 0;
587587
if (fullRestart) {
588-
await generator.reset();
588+
generator.reset();
589589
}
590590
// On a full restart, or on an initial compile for the attach based workflow,
591591
// this will produce a full dill. Subsequent invocations will produce incremental
@@ -614,12 +614,6 @@ class DevFS {
614614
// before processing bundle.
615615
_logger.printTrace('Processing bundle.');
616616
// await null to give time for telling the compiler to compile.
617-
// TODO(andrewkolos): This is a hack. Adding any more awaits to the compiler's
618-
// recompile method will cause this to be insufficent.
619-
// https://github.com/flutter/flutter/issues/151255.
620-
await null;
621-
await null;
622-
await null;
623617
await null;
624618

625619
// The tool writes the assets into the AssetBundle working dir so that they

packages/flutter_tools/lib/src/isolated/devfs_web.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,7 @@ class WebDevFS implements DevFS {
10201020
await _validateTemplateFile('flutter_bootstrap.js');
10211021
final DateTime candidateCompileTime = DateTime.now();
10221022
if (fullRestart) {
1023-
await generator.reset();
1023+
generator.reset();
10241024
}
10251025

10261026
// The tool generates an entrypoint file in a temp directory to handle

packages/flutter_tools/lib/src/isolated/resident_web_runner.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
334334
appFailedToStart();
335335
return 1;
336336
}
337-
await device!.generator!.accept();
337+
device!.generator!.accept();
338338
cacheInitialDillCompilation();
339339
} else {
340340
final WebBuilder webBuilder = WebBuilder(
@@ -418,7 +418,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
418418
// Full restart is always false for web, since the extra recompile is wasteful.
419419
final UpdateFSReport report = await _updateDevFS();
420420
if (report.success) {
421-
await device!.generator!.accept();
421+
device!.generator!.accept();
422422
} else {
423423
status.stop();
424424
await device!.generator!.reject();

packages/flutter_tools/lib/src/resident_runner.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ class FlutterDevice {
595595

596596
Future<void> updateReloadStatus(bool wasReloadSuccessful) async {
597597
if (wasReloadSuccessful) {
598-
await generator?.accept();
598+
generator?.accept();
599599
} else {
600600
await generator?.reject();
601601
}

packages/flutter_tools/lib/src/run_hot.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ class HotRunner extends ResidentRunner {
298298
// VM must have accepted the kernel binary, there will be no reload
299299
// report, so we let incremental compiler know that source code was accepted.
300300
if (device!.generator != null) {
301-
await device.generator!.accept();
301+
device.generator!.accept();
302302
}
303303
final List<FlutterView> views = await device.vmService!.getFlutterViews();
304304
for (final FlutterView view in views) {
@@ -626,7 +626,7 @@ class HotRunner extends ResidentRunner {
626626
// VM must have accepted the kernel binary, there will be no reload
627627
// report, so we let incremental compiler know that source code was accepted.
628628
if (device!.generator != null) {
629-
await device.generator!.accept();
629+
device.generator!.accept();
630630
}
631631
}
632632
// Check if the isolate is paused and resume it.

packages/flutter_tools/lib/src/test/runner.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ class SpawnPlugin extends PlatformPlugin {
647647
fs: globals.fs,
648648
nativeAssetsYaml: nativeAssetsYaml,
649649
);
650-
await residentCompiler.accept();
650+
residentCompiler.accept();
651651

652652
globals.printTrace('Compiling ${sourceFile.absolute.uri} took ${compilerTime.elapsedMilliseconds}ms');
653653
testTimeRecorder?.stop(TestTimePhases.Compile, testTimeRecorderStopwatch!);

packages/flutter_tools/lib/src/test/test_compiler.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,9 @@ class TestCompiler {
188188
// compiler to avoid reusing compiler that might have gotten into
189189
// a weird state.
190190
if (outputPath == null || compilerOutput!.errorCount > 0) {
191-
await _shutdown();
192191
request.result.complete();
192+
await _shutdown();
193193
} else {
194-
await compiler!.accept();
195-
await compiler!.reset();
196194
if (shouldCopyDillFile) {
197195
final String path = request.mainUri.toFilePath(windows: globals.platform.isWindows);
198196
final File outputFile = globals.fs.file(outputPath);
@@ -211,6 +209,8 @@ class TestCompiler {
211209
} else {
212210
request.result.complete(outputPath);
213211
}
212+
compiler!.accept();
213+
compiler!.reset();
214214
}
215215
globals.printTrace('Compiling ${request.mainUri} took ${compilerTime.elapsedMilliseconds}ms');
216216
testTimeRecorder?.stop(TestTimePhases.Compile, testTimeRecorderStopwatch!);

packages/flutter_tools/test/general.shard/compile_incremental_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ Future<void> _accept(
521521
MemoryIOSink frontendServerStdIn,
522522
String expected,
523523
) async {
524-
await generator.accept();
524+
generator.accept();
525525
final String commands = frontendServerStdIn.getAndClear();
526526
final RegExp re = RegExp(expected);
527527
expect(commands, matches(re));

0 commit comments

Comments
 (0)