Skip to content

Commit f6f82c3

Browse files
committed
8266421: Deadlock in Sound System
Reviewed-by: prr, azvegint
1 parent bcaa2cb commit f6f82c3

File tree

4 files changed

+117
-22
lines changed

4 files changed

+117
-22
lines changed

src/java.desktop/share/classes/com/sun/media/sound/AbstractDataLine.java

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -295,13 +295,7 @@ final void setActive(boolean active) {
295295
//boolean sendEvents = false;
296296
//long position = getLongFramePosition();
297297

298-
synchronized (this) {
299-
300-
if (this.active != active) {
301-
this.active = active;
302-
//sendEvents = true;
303-
}
304-
}
298+
this.active = active;
305299

306300
// $$kk: 11.19.99: take ACTIVE / INACTIVE / EOM events out;
307301
// putting them in is technically an API change.
@@ -324,12 +318,9 @@ final void setStarted(boolean started) {
324318
boolean sendEvents = false;
325319
long position = getLongFramePosition();
326320

327-
synchronized (this) {
328-
329-
if (this.started != started) {
330-
this.started = started;
331-
sendEvents = true;
332-
}
321+
if (this.started != started) {
322+
this.started = started;
323+
sendEvents = true;
333324
}
334325

335326
if (sendEvents) {

src/java.desktop/share/classes/com/sun/media/sound/AbstractLine.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -159,11 +159,9 @@ final void setOpen(boolean open) {
159159
boolean sendEvents = false;
160160
long position = getLongFramePosition();
161161

162-
synchronized (this) {
163-
if (this.open != open) {
164-
this.open = open;
165-
sendEvents = true;
166-
}
162+
if (this.open != open) {
163+
this.open = open;
164+
sendEvents = true;
167165
}
168166

169167
if (sendEvents) {

src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -1192,7 +1192,7 @@ public long getLongFramePosition() {
11921192
}
11931193

11941194
@Override
1195-
public synchronized void setMicrosecondPosition(long microseconds) {
1195+
public void setMicrosecondPosition(long microseconds) {
11961196
long frames = Toolkit.micros2frames(getFormat(), microseconds);
11971197
setFramePosition((int) frames);
11981198
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import javax.sound.sampled.AudioFormat;
25+
import javax.sound.sampled.AudioSystem;
26+
import javax.sound.sampled.Clip;
27+
import javax.sound.sampled.LineUnavailableException;
28+
29+
/**
30+
* @test
31+
* @bug 8266421
32+
* @summary Tests that Clip.setFramePosition/setMicrosecondPosition do not hang.
33+
*/
34+
public final class SetPositionHang implements Runnable {
35+
36+
private static volatile boolean testFramePosition;
37+
private final Clip clip;
38+
private final String thread;
39+
40+
private SetPositionHang(String thread, Clip clip) {
41+
this.thread = thread;
42+
this.clip = clip;
43+
}
44+
45+
public static void main(String[] args) throws Exception {
46+
testFramePosition = false;
47+
test();
48+
testFramePosition = true;
49+
test();
50+
}
51+
52+
private static void test() throws InterruptedException {
53+
try (Clip clip = AudioSystem.getClip()) {
54+
// prepare audio data
55+
int frameCount = 441000; // lets say 10 seconds
56+
AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false);
57+
byte[] bytes = new byte[frameCount * format.getFrameSize()];
58+
59+
clip.open(format, bytes, 0, frameCount);
60+
Thread t1 = new Thread(new SetPositionHang("1", clip));
61+
Thread t2 = new Thread(new SetPositionHang("2", clip));
62+
Thread t3 = new Thread(new SetPositionHang("3", clip));
63+
Thread t4 = new Thread(new SetPositionHang("4", clip));
64+
Thread t5 = new Thread(new SetPositionHang("5", clip));
65+
t1.start();
66+
t2.start();
67+
t3.start();
68+
t4.start();
69+
t5.start();
70+
t1.join();
71+
t2.join();
72+
t3.join();
73+
t4.join();
74+
t5.join();
75+
} catch (LineUnavailableException | IllegalArgumentException ignored) {
76+
// the test is not applicable
77+
}
78+
}
79+
80+
public void run() {
81+
System.out.println("Thread " + thread + " Start");
82+
for (int i = 0; i < 100; i++) {
83+
// System.out.println("Thread " + thread + " Play " +
84+
// System.currentTimeMillis() % 100000);
85+
playSound();
86+
try {
87+
Thread.sleep(i);
88+
} catch (InterruptedException e) {
89+
throw new RuntimeException(e);
90+
}
91+
}
92+
System.out.println("Thread " + thread + " Finish");
93+
}
94+
95+
private void playSound() {
96+
if (clip.isRunning()) {
97+
clip.stop();
98+
}
99+
if (testFramePosition) {
100+
clip.setFramePosition(0);
101+
} else {
102+
clip.setMicrosecondPosition(0);
103+
}
104+
clip.start();
105+
}
106+
}

0 commit comments

Comments
 (0)