Unverified Commit 0bab3604 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Make the startup lock message print to stderr. (#86520)

This changes the "Waiting for another flutter command to release the startup lock..." message output so that it appears on stderr instead of stdout. When it appears on stdout, it can mess up collection of the output. For instance, if you run flutter --version --machine and you're expecting JSON output, then you'll get non-JSON output even though the lock is released and you eventually would get what you're asking for.
parent e89747ab
......@@ -17,6 +17,7 @@ import 'base/logger.dart';
import 'base/net.dart';
import 'base/os.dart' show OperatingSystemUtils;
import 'base/platform.dart';
import 'base/terminal.dart';
import 'base/user_messages.dart';
import 'build_info.dart';
import 'convert.dart';
......@@ -320,7 +321,13 @@ class Cache {
} on FileSystemException {
if (!printed) {
_logger.printTrace('Waiting to be able to obtain lock of Flutter binary artifacts directory: ${_lock!.path}');
_logger.printStatus('Waiting for another flutter command to release the startup lock...');
// This needs to go to stderr to avoid cluttering up stdout if a parent
// process is collecting stdout. It's not really an "error" though,
// so print it in grey.
_logger.printError(
'Waiting for another flutter command to release the startup lock...',
color: TerminalColor.grey,
);
printed = true;
}
await Future<void>.delayed(const Duration(milliseconds: 50));
......
......@@ -78,16 +78,22 @@ void main() {
});
testWithoutContext('should not throw when lock is acquired', () async {
final String oldRoot = Cache.flutterRoot;
Cache.flutterRoot = '';
final FileSystem fileSystem = MemoryFileSystem.test();
final Cache cache = Cache.test(fileSystem: fileSystem, processManager: FakeProcessManager.any());
fileSystem.file(fileSystem.path.join('bin', 'cache', 'lockfile'))
.createSync(recursive: true);
await cache.lock();
expect(cache.checkLockAcquired, returnsNormally);
expect(cache.releaseLock, returnsNormally);
try {
final FileSystem fileSystem = MemoryFileSystem.test();
final Cache cache = Cache.test(
fileSystem: fileSystem, processManager: FakeProcessManager.any());
fileSystem.file(fileSystem.path.join('bin', 'cache', 'lockfile'))
.createSync(recursive: true);
await cache.lock();
expect(cache.checkLockAcquired, returnsNormally);
expect(cache.releaseLock, returnsNormally);
} finally {
Cache.flutterRoot = oldRoot;
}
}, skip: true); // TODO(jonahwilliams): implement support for lock so this can be tested with the memory file system.
testWithoutContext('throws tool exit when lockfile open fails', () async {
......
// Copyright 2014 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.
// @dart = 2.8
import 'dart:io' as io show ProcessSignal;
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:process/process.dart';
import '../src/common.dart';
import '../src/context.dart';
import 'test_utils.dart';
final String dart = fileSystem.path
.join(getFlutterRoot(), 'bin', platform.isWindows ? 'dart.bat' : 'dart');
void main() {
group('Cache.lock', () {
// Windows locking is too flaky for this to work reliably.
if (!platform.isWindows) {
testWithoutContext(
'should log a message to stderr when lock is not acquired', () async {
final String oldRoot = Cache.flutterRoot;
final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('cache_test.');
final BufferLogger logger = BufferLogger(
terminal: Terminal.test(supportsColor: false, supportsEmoji: false),
outputPreferences: OutputPreferences(),
);
try {
Cache.flutterRoot = tempDir.absolute.path;
final Cache cache = Cache.test(
fileSystem: fileSystem,
processManager: FakeProcessManager.any(),
logger: logger,
);
final File cacheFile = fileSystem.file(fileSystem.path
.join(Cache.flutterRoot, 'bin', 'cache', 'lockfile'))
..createSync(recursive: true);
final File script = fileSystem.file(fileSystem.path
.join(Cache.flutterRoot, 'bin', 'cache', 'test_lock.dart'));
script.writeAsStringSync(r'''
import 'dart:async';
import 'dart:io';
Future<void> main(List<String> args) async {
File file = File(args[0]);
RandomAccessFile lock = file.openSync(mode: FileMode.write);
lock.lockSync();
await Future<void>.delayed(const Duration(milliseconds: 1000));
exit(0);
}
''');
final Process process = await const LocalProcessManager().start(
<String>[dart, script.absolute.path, cacheFile.absolute.path],
);
await Future<void>.delayed(const Duration(milliseconds: 500));
await cache.lock();
process.kill(io.ProcessSignal.sigkill);
} finally {
try {
tempDir.deleteSync(recursive: true);
} on FileSystemException {
// Ignore filesystem exceptions when trying to delete tempdir.
}
Cache.flutterRoot = oldRoot;
}
expect(logger.statusText, isEmpty);
expect(logger.errorText,
equals('Waiting for another flutter command to release the startup lock...\n'));
});
}
});
}
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