Skip to content

Commit ff14ed4

Browse files
committed
8292695: SIGQUIT and jcmd attaching mechanism does not work with signal chaining library
8283337: Posix signal handler modification warning triggering incorrectly Reviewed-by: manc, mdoerr Backport-of: 45ff10cc68296c7c73d0eafe6fcc9946ab98267e
1 parent f2a10fd commit ff14ed4

File tree

4 files changed

+127
-19
lines changed

4 files changed

+127
-19
lines changed

src/hotspot/os/posix/signals_posix.cpp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ static const struct {
341341
};
342342

343343
////////////////////////////////////////////////////////////////////////////////
344-
// sun.misc.Signal support
344+
// sun.misc.Signal and BREAK_SIGNAL support
345345

346346
void jdk_misc_signal_init() {
347347
// Initialize signal structures
@@ -562,11 +562,6 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info,
562562
{
563563
assert(info != NULL && ucVoid != NULL, "sanity");
564564

565-
if (sig == BREAK_SIGNAL) {
566-
assert(!ReduceSignalUsage, "Should not happen with -Xrs/-XX:+ReduceSignalUsage");
567-
return true; // ignore it
568-
}
569-
570565
// Note: it's not uncommon that JNI code uses signal/sigset to install,
571566
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
572567
// or have a SIGILL handler when detecting CPU type). When that happens,
@@ -1202,7 +1197,7 @@ int os::get_signal_number(const char* signal_name) {
12021197
return -1;
12031198
}
12041199

1205-
void set_signal_handler(int sig, bool do_check = true) {
1200+
void set_signal_handler(int sig) {
12061201
// Check for overwrite.
12071202
struct sigaction oldAct;
12081203
sigaction(sig, (struct sigaction*)NULL, &oldAct);
@@ -1244,9 +1239,10 @@ void set_signal_handler(int sig, bool do_check = true) {
12441239
}
12451240
#endif
12461241

1247-
// Save handler setup for later checking
1242+
// Save handler setup for possible later checking
12481243
vm_handlers.set(sig, &sigAct);
1249-
do_check_signal_periodically[sig] = do_check;
1244+
1245+
do_check_signal_periodically[sig] = true;
12501246

12511247
int ret = sigaction(sig, &sigAct, &oldAct);
12521248
assert(ret == 0, "check");
@@ -1285,11 +1281,24 @@ void install_signal_handlers() {
12851281
PPC64_ONLY(set_signal_handler(SIGTRAP);)
12861282
set_signal_handler(SIGXFSZ);
12871283
if (!ReduceSignalUsage) {
1288-
// This is just for early initialization phase. Intercepting the signal here reduces the risk
1289-
// that an attach client accidentally forces HotSpot to quit prematurely. We skip the periodic
1290-
// check because late initialization will overwrite it to UserHandler.
1291-
set_signal_handler(BREAK_SIGNAL, false);
1284+
// Install BREAK_SIGNAL's handler in early initialization phase, in
1285+
// order to reduce the risk that an attach client accidentally forces
1286+
// HotSpot to quit prematurely.
1287+
// The actual work for handling BREAK_SIGNAL is performed by the Signal
1288+
// Dispatcher thread, which is created and started at a much later point,
1289+
// see os::initialize_jdk_signal_support(). Any BREAK_SIGNAL received
1290+
// before the Signal Dispatcher thread is started is queued up via the
1291+
// pending_signals[BREAK_SIGNAL] counter, and will be processed by the
1292+
// Signal Dispatcher thread in a delayed fashion.
1293+
//
1294+
// Also note that HotSpot does NOT support signal chaining for BREAK_SIGNAL.
1295+
// Applications that require a custom BREAK_SIGNAL handler should run with
1296+
// -XX:+ReduceSignalUsage. Otherwise if libjsig is used together with
1297+
// -XX:+ReduceSignalUsage, libjsig will prevent changing BREAK_SIGNAL's
1298+
// handler to a custom handler.
1299+
os::signal(BREAK_SIGNAL, os::user_handler());
12921300
}
1301+
12931302
#if defined(__APPLE__)
12941303
// lldb (gdb) installs both standard BSD signal handlers, and mach exception
12951304
// handlers. By replacing the existing task exception handler, we disable lldb's mach
@@ -1784,12 +1793,12 @@ int PosixSignals::init() {
17841793

17851794
signal_sets_init();
17861795

1787-
install_signal_handlers();
1788-
1789-
// Initialize data for jdk.internal.misc.Signal
1796+
// Initialize data for jdk.internal.misc.Signal and BREAK_SIGNAL's handler.
17901797
if (!ReduceSignalUsage) {
17911798
jdk_misc_signal_init();
17921799
}
17931800

1801+
install_signal_handlers();
1802+
17941803
return JNI_OK;
17951804
}

src/hotspot/os/windows/os_windows.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2266,6 +2266,15 @@ static void jdk_misc_signal_init() {
22662266

22672267
// Add a CTRL-C handler
22682268
SetConsoleCtrlHandler(consoleHandler, TRUE);
2269+
2270+
// Initialize sigbreakHandler.
2271+
// The actual work for handling CTRL-BREAK is performed by the Signal
2272+
// Dispatcher thread, which is created and started at a much later point,
2273+
// see os::initialize_jdk_signal_support(). Any CTRL-BREAK received
2274+
// before the Signal Dispatcher thread is started is queued up via the
2275+
// pending_signals[SIGBREAK] counter, and will be processed by the
2276+
// Signal Dispatcher thread in a delayed fashion.
2277+
os::signal(SIGBREAK, os::user_handler());
22692278
}
22702279

22712280
void os::signal_notify(int sig) {
@@ -4386,7 +4395,8 @@ jint os::init_2(void) {
43864395

43874396
SymbolEngine::recalc_search_path();
43884397

4389-
// Initialize data for jdk.internal.misc.Signal
4398+
// Initialize data for jdk.internal.misc.Signal, and install CTRL-C and
4399+
// CTRL-BREAK handlers.
43904400
if (!ReduceSignalUsage) {
43914401
jdk_misc_signal_init();
43924402
}

src/hotspot/share/runtime/os.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,8 +513,6 @@ void os::initialize_jdk_signal_support(TRAPS) {
513513
Threads::add(signal_thread);
514514
Thread::start(signal_thread);
515515
}
516-
// Handle ^BREAK
517-
os::signal(SIGBREAK, os::user_handler());
518516
}
519517
}
520518

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2022, Google and/or its affiliates. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
/*
26+
* @test id=default
27+
* @bug 8292695
28+
* @summary Check that Ctrl-\ or Ctrl-Break (on Windows) causes HotSpot VM to print a full thread dump.
29+
* @library /vmTestbase
30+
* /test/lib
31+
* @run driver TestBreakSignalThreadDump
32+
*/
33+
34+
/*
35+
* @test id=with_jsig
36+
* @bug 8292695
37+
* @summary Check that Ctrl-\ causes HotSpot VM to print a full thread dump when signal chaining is used.
38+
* @requires os.family != "windows" & os.family != "aix"
39+
* @library /vmTestbase
40+
* /test/lib
41+
* @run driver TestBreakSignalThreadDump load_libjsig
42+
*/
43+
44+
import java.nio.file.Files;
45+
import java.nio.file.Path;
46+
import java.util.Map;
47+
import jdk.test.lib.Platform;
48+
import jdk.test.lib.Utils;
49+
import jdk.test.lib.process.ProcessTools;
50+
import jdk.test.lib.process.OutputAnalyzer;
51+
import vm.share.ProcessUtils;
52+
53+
public class TestBreakSignalThreadDump {
54+
55+
static class TestProcess {
56+
static {
57+
System.loadLibrary("ProcessUtils");
58+
}
59+
60+
public static void main(String[] argv) throws Exception {
61+
ProcessUtils.sendCtrlBreak();
62+
// Wait a bit, as JVM processes the break signal asynchronously.
63+
Thread.sleep(1000);
64+
System.out.println("Done!");
65+
}
66+
}
67+
68+
public static void main(String[] argv) throws Exception {
69+
String main = "TestBreakSignalThreadDump$TestProcess";
70+
ProcessBuilder pb = ProcessTools.createTestJvm("-Djava.library.path=" + Utils.TEST_NATIVE_PATH, main);
71+
72+
if (argv.length > 0 && argv[0].equals("load_libjsig")) {
73+
prepend_jsig_lib(pb.environment());
74+
}
75+
76+
OutputAnalyzer output = new OutputAnalyzer(pb.start());
77+
output.shouldHaveExitValue(0);
78+
output.shouldContain("Full thread dump ");
79+
output.shouldContain("java.lang.Thread.State: RUNNABLE");
80+
output.shouldContain("Done!");
81+
}
82+
83+
private static void prepend_jsig_lib(Map<String, String> env) {
84+
Path libjsig = Platform.jvmLibDir().resolve("libjsig." + Platform.sharedLibraryExt());
85+
if (!Files.exists(libjsig)) {
86+
throw new RuntimeException("File libjsig not found, path: " + libjsig);
87+
}
88+
String env_var = Platform.isOSX() ? "DYLD_INSERT_LIBRARIES" : "LD_PRELOAD";
89+
env.put(env_var, libjsig.toString());
90+
}
91+
}

0 commit comments

Comments
 (0)