Skip to content

Commit b91c82d

Browse files
hborchardtjkrems
authored andcommitted
fix(@angular/build): avoid race condition in sass importer
On slow systems, a race condition can lead to the sass worker thread being notified to wake up before a message is posted. This causes the build to be aborted because the searched file is not found. Waiting twice for a non-zero number in the signal handles this race correctly, and the second wait should be a noop in the usual case. Fixes #27167 (cherry picked from commit 5f473af)
1 parent 237f7c5 commit b91c82d

File tree

1 file changed

+19
-0
lines changed
  • packages/angular/build/src/tools/sass

1 file changed

+19
-0
lines changed

packages/angular/build/src/tools/sass/worker.ts

+19
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ export default async function renderSassStylesheet(request: RenderRequestMessage
8080
containingUrl: containingUrl ? fileURLToPath(containingUrl) : null,
8181
},
8282
});
83+
// Wait for the main thread to set the signal to 1 and notify, which tells
84+
// us that a message can be received on the port.
85+
// If the main thread is fast, the signal will already be set to 1, and no
86+
// sleep/notify is necessary.
87+
// However, there can be a race condition here:
88+
// - the main thread sets the signal to 1, but does not get to the notify instruction yet
89+
// - the worker does not pause because the signal is set to 1
90+
// - the worker very soon enters this method again
91+
// - this method sets the signal to 0 and sends the message
92+
// - the signal is 0 and so the `Atomics.wait` call blocks
93+
// - only now the main thread runs the `notify` from the first invocation, so the
94+
// worker continues.
95+
// - but there is no message yet in the port, because the thread should not have been
96+
// waken up yet.
97+
// To combat this, wait for a non-0 value _twice_.
98+
// Almost every time, this immediately continues with "not-equal", because
99+
// the signal is still set to 1, except during the race condition, when the second
100+
// wait will wait for the correct notify.
101+
Atomics.wait(importerChannel.signal, 0, 0);
83102
Atomics.wait(importerChannel.signal, 0, 0);
84103

85104
const result = receiveMessageOnPort(importerChannel.port)?.message as string | null;

0 commit comments

Comments
 (0)