Skip to content

Commit ec53e00

Browse files
Jiří VaněkPaul Hohensee
Jiří Vaněk
authored and
Paul Hohensee
committedFeb 15, 2023
8282947: JFR: Dump on shutdown live-locks in some conditions
Reviewed-by: phh Backport-of: 63eb0b7e8606dd9cd145e92eeeb744ff5b7be569
1 parent c183dc5 commit ec53e00

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed
 

‎jdk/src/share/classes/jdk/jfr/internal/ChunksChannel.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,13 @@ public long transferTo(FileChannel out) throws IOException {
9696
assert current != null;
9797

9898
long rem = current.getSize();
99-
10099
while (rem > 0) {
101100
long n = Math.min(rem, 1024 * 1024);
102101
long w = out.transferFrom(channel, pos, n);
102+
// Prevent endless loop
103+
if (w == 0) {
104+
return out.size();
105+
}
103106
pos += w;
104107
rem -= w;
105108
}
@@ -111,7 +114,7 @@ public long transferTo(FileChannel out) throws IOException {
111114
current = null;
112115
}
113116
if (!nextChannel()) {
114-
return pos;
117+
return out.size();
115118
}
116119
}
117120
}

‎jdk/src/share/classes/jdk/jfr/internal/PlatformRecording.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -682,8 +682,12 @@ public void dumpStopped(WriteableUserPath userPath) throws IOException {
682682
synchronized (recorder) {
683683
userPath.doPriviligedIO(() -> {
684684
try (ChunksChannel cc = new ChunksChannel(chunks); FileChannel fc = FileChannel.open(userPath.getReal(), StandardOpenOption.WRITE, StandardOpenOption.APPEND)) {
685-
cc.transferTo(fc);
686-
fc.force(true);
685+
long bytes = cc.transferTo(fc);
686+
Logger.log(LogTag.JFR, LogLevel.INFO, "Transferred " + bytes + " bytes from the disk repository");
687+
// No need to force if no data was transferred, which avoids IOException when device is /dev/null
688+
if (bytes != 0) {
689+
fc.force(true);
690+
}
687691
}
688692
return null;
689693
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2022, 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+
package jdk.jfr.api.recording.dump;
25+
26+
import java.io.File;
27+
28+
import jdk.jfr.Recording;
29+
30+
/**
31+
* @test
32+
* @summary Tests that it's possible to dump to /dev/null without a livelock
33+
* @key jfr
34+
*
35+
* @library /lib /
36+
* @run main/othervm jdk.jfr.api.recording.dump.TestDumpDevNull
37+
*/
38+
public class TestDumpDevNull {
39+
40+
public static void main(String[] args) throws Exception {
41+
try (Recording r1 = new Recording()) {
42+
r1.setDestination(new File("/dev/null").toPath());
43+
r1.start();
44+
// Force a chunk rotation which ensures that jdk.jfr.internal.ChunkChannel
45+
// invokes FileChannel::transferFrom(ReadableByteChannel, position, count) twice.
46+
// FileChannel will return 0 the second time because position exceeds
47+
// FileChannel::size(), which is always 0 for /dev/null
48+
// Without proper handling of return value 0, the ChunkChannel will spin indefinitely.
49+
try (Recording r2 = new Recording()) {
50+
r2.start();
51+
}
52+
}
53+
}
54+
}

0 commit comments

Comments
 (0)
Please sign in to comment.