Skip to content

Commit 12df326

Browse files
committed
Crash under FFTFrame::fftSetupForSize()
https://bugs.webkit.org/show_bug.cgi?id=220866 <rdar://73199504> Reviewed by Eric Carlson. Source/WebCore: The crash was caused by FFTFrame::fftSetupForSize() but being called concurrently from "HRTF database loader" threads. This patch makes FFTFrame::fftSetupForSize() thread safe to address the issue. Test: webaudio/Panner/PannerNode-crash.html * platform/audio/mac/FFTFrameMac.cpp: (WebCore::fftSetups): (WebCore::FFTFrame::fftSetupForSize): LayoutTests: Add layout test coverage. * webaudio/Panner/PannerNode-crash-expected.txt: Added. * webaudio/Panner/PannerNode-crash.html: Added. Canonical link: https://commits.webkit.org/233258@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271751 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 73df819 commit 12df326

5 files changed

Lines changed: 85 additions & 4 deletions

File tree

LayoutTests/ChangeLog

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
2021-01-22 Chris Dumez <cdumez@apple.com>
2+
3+
Crash under FFTFrame::fftSetupForSize()
4+
https://bugs.webkit.org/show_bug.cgi?id=220866
5+
<rdar://73199504>
6+
7+
Reviewed by Eric Carlson.
8+
9+
Add layout test coverage.
10+
11+
* webaudio/Panner/PannerNode-crash-expected.txt: Added.
12+
* webaudio/Panner/PannerNode-crash.html: Added.
13+
114
2021-01-22 Youenn Fablet <youenn@apple.com>
215

316
Add more descriptive messages to setLocalDescription/setRemoteDescription error cases
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
This test passes if it does not crash.
2+
3+
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4+
5+
6+
PASS successfullyParsed is true
7+
8+
TEST COMPLETE
9+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<body>
4+
<script src="../../resources/js-test.js"></script>
5+
<script>
6+
description("This test passes if it does not crash.");
7+
jsTestIsAsync = true;
8+
9+
const random = (min, max) => {
10+
let num = Math.random() * (max - min) + min;
11+
12+
return Math.round(num);
13+
};
14+
15+
onload = () => {
16+
for (let i = 0; i < 50; i++) {
17+
let sampleRate = random(3000, 384000);
18+
new PannerNode(new OfflineAudioContext({length: 128, sampleRate: sampleRate}));
19+
new OfflineAudioContext({length: 128, sampleRate: sampleRate}).createPanner().disconnect();
20+
}
21+
22+
setTimeout(finishJSTest, 100);
23+
};
24+
</script>
25+
</body>
26+
</html>

Source/WebCore/ChangeLog

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
2021-01-22 Chris Dumez <cdumez@apple.com>
2+
3+
Crash under FFTFrame::fftSetupForSize()
4+
https://bugs.webkit.org/show_bug.cgi?id=220866
5+
<rdar://73199504>
6+
7+
Reviewed by Eric Carlson.
8+
9+
The crash was caused by FFTFrame::fftSetupForSize() but being called concurrently
10+
from "HRTF database loader" threads. This patch makes FFTFrame::fftSetupForSize()
11+
thread safe to address the issue.
12+
13+
Test: webaudio/Panner/PannerNode-crash.html
14+
15+
* platform/audio/mac/FFTFrameMac.cpp:
16+
(WebCore::fftSetups):
17+
(WebCore::FFTFrame::fftSetupForSize):
18+
119
2021-01-22 Youenn Fablet <youenn@apple.com>
220

321
Add more descriptive messages to setLocalDescription/setRemoteDescription error cases

Source/WebCore/platform/audio/mac/FFTFrameMac.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "FFTFrame.h"
3838

3939
#include "VectorMath.h"
40+
#include <wtf/Lock.h>
4041
#include <wtf/NeverDestroyed.h>
4142
#include <wtf/Vector.h>
4243

@@ -121,15 +122,29 @@ void FFTFrame::doInverseFFT(float* data)
121122
VectorMath::multiplyByScalar(data, 1.0f / m_FFTSize, data, m_FFTSize);
122123
}
123124

125+
static Vector<FFTSetup>& fftSetups()
126+
{
127+
static LazyNeverDestroyed<Vector<FFTSetup>> fftSetups;
128+
static std::once_flag onceKey;
129+
std::call_once(onceKey, [&] {
130+
fftSetups.construct(kMaxFFTPow2Size, nullptr);
131+
});
132+
return fftSetups;
133+
}
134+
124135
FFTSetup FFTFrame::fftSetupForSize(unsigned fftSize)
125136
{
126-
static NeverDestroyed<Vector<FFTSetup>> fftSetups(kMaxFFTPow2Size, nullptr);
137+
static Lock fftSetupsLock;
127138

128139
auto pow2size = static_cast<size_t>(log2(fftSize));
129140
ASSERT(pow2size < kMaxFFTPow2Size);
130-
auto& fftSetup = fftSetups->at(pow2size);
131-
if (!fftSetup)
132-
fftSetup = vDSP_create_fftsetup(pow2size, FFT_RADIX2);
141+
142+
auto& fftSetup = fftSetups().at(pow2size);
143+
if (!fftSetup) {
144+
auto locker = holdLock(fftSetupsLock);
145+
if (!fftSetup)
146+
fftSetup = vDSP_create_fftsetup(pow2size, FFT_RADIX2);
147+
}
133148

134149
return fftSetup;
135150
}

0 commit comments

Comments
 (0)