mirror of
https://github.com/danog/dart-sass.git
synced 2024-12-02 09:37:49 +01:00
Fix race condition between spawning and killing isolates during shutdown (#2007)
Co-authored-by: Natalie Weizenbaum <nweiz@google.com>
This commit is contained in:
parent
760fa2ead1
commit
aa59a5f4a9
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
### Embedded Sass
|
### Embedded Sass
|
||||||
|
|
||||||
|
* Fix a race condition where closing standard input while requests are in-flight
|
||||||
|
could sometimes cause the process to hang rather than shutting down
|
||||||
|
gracefully.
|
||||||
|
|
||||||
* Properly include the root stylesheet's URL in the set of loaded URLs when it
|
* Properly include the root stylesheet's URL in the set of loaded URLs when it
|
||||||
fails to parse.
|
fails to parse.
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ class IsolateDispatcher {
|
|||||||
/// The actual isolate objects that have been spawned.
|
/// The actual isolate objects that have been spawned.
|
||||||
///
|
///
|
||||||
/// Only used for cleaning up the process when the underlying channel closes.
|
/// Only used for cleaning up the process when the underlying channel closes.
|
||||||
final _allIsolates = <Isolate>[];
|
final _allIsolates = <Future<Isolate>>[];
|
||||||
|
|
||||||
/// A pool controlling how many isolates (and thus concurrent compilations)
|
/// A pool controlling how many isolates (and thus concurrent compilations)
|
||||||
/// may be live at once.
|
/// may be live at once.
|
||||||
@ -101,10 +101,10 @@ class IsolateDispatcher {
|
|||||||
}
|
}
|
||||||
}, onError: (Object error, StackTrace stackTrace) {
|
}, onError: (Object error, StackTrace stackTrace) {
|
||||||
_handleError(error, stackTrace);
|
_handleError(error, stackTrace);
|
||||||
}, onDone: () {
|
}, onDone: () async {
|
||||||
_closed = true;
|
_closed = true;
|
||||||
for (var isolate in _allIsolates) {
|
for (var isolate in _allIsolates) {
|
||||||
isolate.kill();
|
(await isolate).kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Killing isolates isn't sufficient to make sure the process closes; we
|
// Killing isolates isn't sufficient to make sure the process closes; we
|
||||||
@ -130,7 +130,9 @@ class IsolateDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var receivePort = ReceivePort();
|
var receivePort = ReceivePort();
|
||||||
_allIsolates.add(await Isolate.spawn(_isolateMain, receivePort.sendPort));
|
var future = Isolate.spawn(_isolateMain, receivePort.sendPort);
|
||||||
|
_allIsolates.add(future);
|
||||||
|
await future;
|
||||||
|
|
||||||
var channel = IsolateChannel<_InitialMessage?>.connectReceive(receivePort)
|
var channel = IsolateChannel<_InitialMessage?>.connectReceive(receivePort)
|
||||||
.transform(const ExplicitCloseTransformer());
|
.transform(const ExplicitCloseTransformer());
|
||||||
|
@ -224,6 +224,19 @@ void main() {
|
|||||||
await process.shouldExit(0);
|
await process.shouldExit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("closes gracefully with many in-flight compilations", () async {
|
||||||
|
// This should always be equal to the size of
|
||||||
|
// [IsolateDispatcher._isolatePool], since that's as many concurrent
|
||||||
|
// compilations as we can realistically have anyway.
|
||||||
|
var totalRequests = 15;
|
||||||
|
for (var i = 1; i <= totalRequests; i++) {
|
||||||
|
process.inbound
|
||||||
|
.add((i, compileString("a {b: foo() + 2px}", functions: [r"foo()"])));
|
||||||
|
}
|
||||||
|
|
||||||
|
await process.close();
|
||||||
|
}, skip: "Enable once dart-lang/stream_channel#92 is released");
|
||||||
|
|
||||||
test("doesn't include a source map by default", () async {
|
test("doesn't include a source map by default", () async {
|
||||||
process.send(compileString("a {b: 1px + 2px}"));
|
process.send(compileString("a {b: 1px + 2px}"));
|
||||||
await expectSuccess(process, "a { b: 3px; }", sourceMap: isEmpty);
|
await expectSuccess(process, "a { b: 3px; }", sourceMap: isEmpty);
|
||||||
|
Loading…
Reference in New Issue
Block a user