1 // Copyright 2021 Code Intelligence GmbH
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "signal_handler.h"
16
17 #include <jni.h>
18
19 #include <atomic>
20 #include <csignal>
21 #include <stdexcept>
22
23 constexpr auto kSignalHandlerClass =
24 "com/code_intelligence/jazzer/runtime/SignalHandler";
25
26 // Handles SIGINT raised while running Java code.
handleInterrupt(JNIEnv,jclass)27 void JNICALL handleInterrupt(JNIEnv, jclass) {
28 static std::atomic<bool> already_exiting{false};
29 if (!already_exiting.exchange(true)) {
30 // Let libFuzzer exit gracefully when the JVM received SIGINT.
31 raise(SIGUSR1);
32 } else {
33 // Exit libFuzzer forcefully on repeated SIGINTs.
34 raise(SIGTERM);
35 }
36 }
37
38 namespace jazzer {
Setup(JNIEnv & env)39 void SignalHandler::Setup(JNIEnv &env) {
40 jclass signal_handler_class = env.FindClass(kSignalHandlerClass);
41 if (env.ExceptionCheck()) {
42 env.ExceptionDescribe();
43 throw std::runtime_error("could not find signal handler class");
44 }
45 JNINativeMethod signal_handler_methods[]{
46 {(char *)"handleInterrupt", (char *)"()V", (void *)&handleInterrupt},
47 };
48 env.RegisterNatives(signal_handler_class, signal_handler_methods, 1);
49 if (env.ExceptionCheck()) {
50 env.ExceptionDescribe();
51 throw std::runtime_error(
52 "could not register native callbacks 'handleInterrupt'");
53 }
54 jmethodID setup_signal_handlers_method_ =
55 env.GetStaticMethodID(signal_handler_class, "setupSignalHandlers", "()V");
56 if (env.ExceptionCheck()) {
57 env.ExceptionDescribe();
58 throw std::runtime_error("could not find setupSignalHandlers method");
59 }
60 env.CallStaticVoidMethod(signal_handler_class, setup_signal_handlers_method_);
61 if (env.ExceptionCheck()) {
62 env.ExceptionDescribe();
63 throw std::runtime_error("failed to set up signal handlers");
64 }
65 }
66 } // namespace jazzer
67