blob: db8dc3df77ec0ee064ea51e1e4e14cb49437b9dc [file] [log] [blame]
/*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "PAL: SignalHandler"
#include <unistd.h>
#include <log/log.h>
#include <chrono>
#include "SignalHandler.h"
#ifdef _ANDROID_
#include <utils/ProcessCallStack.h>
#include <cutils/android_filesystem_config.h>
#endif
std::mutex SignalHandler::sDefaultSigMapLock;
std::unordered_map<int, std::shared_ptr<struct sigaction>> SignalHandler::sDefaultSigMap;
std::function<void(int, pid_t, uid_t)> SignalHandler::sClientCb;
std::mutex SignalHandler::sAsyncRegisterLock;
std::future<void> SignalHandler::sAsyncHandle;
bool SignalHandler::sBuildDebuggable;
// static
void SignalHandler::asyncRegister(int signal) {
std::lock_guard<std::mutex> lock(sAsyncRegisterLock);
sigset_t pendingSigMask;
uint32_t tries = kDefaultSignalPendingTries;
// Delay registration to let default signal handler complete
do {
std::this_thread::sleep_for(
std::chrono::milliseconds(kDefaultRegistrationDelayMs));
sigpending(&pendingSigMask);
--tries;
} while (tries > 0 && sigismember(&pendingSigMask, signal) == 1);
// Register custom handler only if signal is not pending
if (!sigismember(&pendingSigMask, signal)) {
std::vector<int> signals({ signal });
getInstance()->registerSignalHandler(signals);
}
}
// static
void SignalHandler::setClientCallback(std::function<void(int, pid_t, uid_t)> cb) {
sClientCb = cb;
}
// static
std::shared_ptr<SignalHandler> SignalHandler::getInstance() {
static std::shared_ptr<SignalHandler> instance(new SignalHandler());
return instance;
}
// static
void SignalHandler::invokeDefaultHandler(std::shared_ptr<struct sigaction> sAct,
int code, struct siginfo *si, void *sc) {
ALOGV("%s: invoke default handler for signal %d", __func__, code);
// Remove custom handler so that default handler is invoked
sigaction(code, sAct.get(), NULL);
int status = 0;
if (si->si_code == SI_QUEUE) {
ALOGE_IF(code == DEBUGGER_SIGNAL,
"signal %d (<debuggerd signal>), code -1 "
"(SI_QUEUE from pid %d, uid %d)",
code, si->si_pid, si->si_uid);
status = sigqueue(getpid(), code, si->si_value);
#ifdef _ANDROID_
if(isBuildDebuggable() && si->si_uid == AID_AUDIOSERVER) {
std::string prefix = "audioserver_" + std::to_string(si->si_pid) + " ";
android::ProcessCallStack pcs;
pcs.update();
pcs.log(LOG_TAG, ANDROID_LOG_FATAL, prefix.c_str());
}
#endif
} else {
status = raise(code);
}
if (status < 0) {
ALOGW("%s: Sending signal %d failed with error %d",
__func__, code, errno);
}
// Register custom handler back asynchronously
sAsyncHandle = std::async(std::launch::async, SignalHandler::asyncRegister, code);
}
// static
void SignalHandler::customSignalHandler(
int code, struct siginfo *si, void *sc) {
ALOGV("%s: enter", __func__);
std::lock_guard<std::mutex> lock(sDefaultSigMapLock);
if (sClientCb) {
sClientCb(code, si->si_pid, si->si_uid);
}
// Invoke default handler
auto it = sDefaultSigMap.find(code);
if (it != sDefaultSigMap.end()) {
invokeDefaultHandler(it->second, code, si, sc);
}
}
// static
std::vector<int> SignalHandler::getRegisteredSignals() {
std::vector<int> registeredSignals;
std::lock_guard<std::mutex> lock(sDefaultSigMapLock);
for (const auto& element : sDefaultSigMap) {
registeredSignals.push_back(element.first);
}
return registeredSignals;
}
void SignalHandler::registerSignalHandler(std::vector<int> signalsToRegister) {
ALOGV("%s: enter", __func__);
struct sigaction regAction = {};
regAction.sa_sigaction = customSignalHandler;
regAction.sa_flags = SA_SIGINFO | SA_NODEFER;
std::lock_guard<std::mutex> lock(sDefaultSigMapLock);
for (int signal : signalsToRegister) {
ALOGV("%s: register signal %d", __func__, signal);
auto oldSigAction = std::make_shared<struct sigaction>();
if (sigaction(signal, &regAction, oldSigAction.get()) < 0) {
ALOGW("%s: Failed to register handler with error code %d for signal %d",
__func__, errno, signal);
}
sDefaultSigMap.emplace(signal, oldSigAction);
}
}