blob: 61493419fa6f42a6ff2f5df17741d45b52f32786 [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'dart:math' as math;
import 'package:build/build.dart';
import 'package:logging/logging.dart';
import 'package:scratch_space/scratch_space.dart';
import 'workers.dart';
final _logger = Logger('BuildModules');
/// A shared [ScratchSpace] for ddc and analyzer workers that persists
/// throughout builds.
final scratchSpace = ScratchSpace();
/// A shared [Resource] for a [ScratchSpace], which cleans up the contents of
/// the [ScratchSpace] in dispose, but doesn't delete it entirely.
final scratchSpaceResource = Resource<ScratchSpace>(() {
if (!scratchSpace.exists) {
scratchSpace.tempDir.createSync(recursive: true);
scratchSpace.exists = true;
}
return scratchSpace;
}, beforeExit: () async {
// The workers are running inside the scratch space, so wait for them to
// shut down before deleting it.
await dartdevkWorkersAreDone;
await frontendWorkersAreDone;
await dart2jsWorkersAreDone;
// Attempt to clean up the scratch space. Even after waiting for the workers
// to shut down we might get file system exceptions on windows for an
// arbitrary amount of time, so do retries with an exponential backoff.
var numTries = 0;
while (true) {
numTries++;
if (numTries > 3) {
_logger
.warning('Failed to clean up temp dir ${scratchSpace.tempDir.path}.');
return;
}
try {
// TODO(https://github.com/dart-lang/build/issues/656): The scratch
// space throws on `delete` if it thinks it was already deleted.
// Manually clean up in this case.
if (scratchSpace.exists) {
await scratchSpace.delete();
} else {
await scratchSpace.tempDir.delete(recursive: true);
}
return;
} on FileSystemException {
var delayMs = math.pow(10, numTries).floor();
_logger.info('Failed to delete temp dir ${scratchSpace.tempDir.path}, '
'retrying in ${delayMs}ms');
await Future.delayed(Duration(milliseconds: delayMs));
}
}
});