1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "perfetto/ext/base/ctrl_c_handler.h" 18 19 #include "perfetto/base/build_config.h" 20 #include "perfetto/base/compiler.h" 21 #include "perfetto/base/logging.h" 22 23 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 24 #include <Windows.h> 25 #include <io.h> 26 #else 27 #include <signal.h> 28 #include <unistd.h> 29 #endif 30 31 namespace perfetto { 32 namespace base { 33 34 namespace { 35 CtrlCHandlerFunction g_handler = nullptr; 36 } 37 InstallCtrCHandler(CtrlCHandlerFunction handler)38void InstallCtrCHandler(CtrlCHandlerFunction handler) { 39 PERFETTO_CHECK(g_handler == nullptr); 40 g_handler = handler; 41 42 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 43 auto trampoline = [](DWORD type) -> int { 44 if (type == CTRL_C_EVENT) { 45 g_handler(); 46 return true; 47 } 48 return false; 49 }; 50 ::SetConsoleCtrlHandler(trampoline, true); 51 #elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ 52 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ 53 PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) 54 // Setup signal handler. 55 struct sigaction sa {}; 56 57 // Glibc headers for sa_sigaction trigger this. 58 #pragma GCC diagnostic push 59 #if defined(__clang__) 60 #pragma GCC diagnostic ignored "-Wdisabled-macro-expansion" 61 #endif 62 sa.sa_handler = [](int) { g_handler(); }; 63 sa.sa_flags = static_cast<decltype(sa.sa_flags)>(SA_RESETHAND | SA_RESTART); 64 #pragma GCC diagnostic pop 65 sigaction(SIGINT, &sa, nullptr); 66 sigaction(SIGTERM, &sa, nullptr); 67 #else 68 // Do nothing on NaCL and Fuchsia. 69 ignore_result(handler); 70 #endif 71 } 72 73 } // namespace base 74 } // namespace perfetto 75