diff options
Diffstat (limited to 'cmds/runtime/SignalHandler.cpp')
-rw-r--r-- | cmds/runtime/SignalHandler.cpp | 249 |
1 files changed, 0 insertions, 249 deletions
diff --git a/cmds/runtime/SignalHandler.cpp b/cmds/runtime/SignalHandler.cpp deleted file mode 100644 index cccaabf..0000000 --- a/cmds/runtime/SignalHandler.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// -// Copyright 2005 The Android Open Source Project -// - -#define LOG_TAG "SignalHandler" - -#include "SignalHandler.h" - -#include <utils/Atomic.h> -#include <utils/Debug.h> -#include <utils/Log.h> - -#include <errno.h> -#include <sys/wait.h> -#include <unistd.h> - -namespace android { - -class SignalHandler::ProcessThread : public Thread -{ -public: - ProcessThread(SignalHandler& sh) - : Thread(false) - , mOwner(sh) - { - } - - virtual bool threadLoop() - { - char buffer[32]; - read(mOwner.mAvailMsg[0], buffer, sizeof(buffer)); - - LOGV("Signal command processing thread woke up!"); - - if (mOwner.mLostCommands) { - LOGE("Lost %d signals!", mOwner.mLostCommands); - mOwner.mLostCommands = 0; - } - - int cur; - while ((cur=mOwner.mCommandBottom) != mOwner.mCommandTop) { - if (mOwner.mCommands[cur].filled == 0) { - LOGV("Command at %d is not yet filled", cur); - break; - } - - LOGV("Processing command at %d, top is %d", - cur, mOwner.mCommandTop); - processCommand(mOwner.mCommands[cur]); - mOwner.mCommands[cur].filled = 0; - - int next = mOwner.mCommandBottom+1; - if (next >= COMMAND_QUEUE_SIZE) { - next = 0; - } - - mOwner.mCommandBottom = next; - } - - return true; - } - - void processCommand(const CommandEntry& entry) - { - switch (entry.signum) { - case SIGCHLD: { - mOwner.mLock.lock(); - ssize_t i = mOwner.mChildHandlers.indexOfKey(entry.info.si_pid); - ChildHandler ch; - if (i >= 0) { - ch = mOwner.mChildHandlers.valueAt(i); - mOwner.mChildHandlers.removeItemsAt(i); - } - mOwner.mLock.unlock(); - - LOGD("SIGCHLD: pid=%d, handle index=%d", entry.info.si_pid, i); - - if (i >= 0) { - int res = waitpid(entry.info.si_pid, NULL, WNOHANG); - LOGW_IF(res == 0, - "Received SIGCHLD, but pid %d is not yet stopped", - entry.info.si_pid); - if (ch.handler) { - ch.handler(entry.info.si_pid, ch.userData); - } - } else { - LOGW("Unhandled SIGCHLD for pid %d", entry.info.si_pid); - } - } break; - } - } - - SignalHandler& mOwner; -}; - - -Mutex SignalHandler::mInstanceLock; -SignalHandler* SignalHandler::mInstance = NULL; - -status_t SignalHandler::setChildHandler(pid_t childPid, - int tag, - child_callback_t handler, - void* userData) -{ - SignalHandler* const self = getInstance(); - - self->mLock.lock(); - - // First make sure this child hasn't already exited. - pid_t res = waitpid(childPid, NULL, WNOHANG); - if (res != 0) { - if (res < 0) { - LOGW("setChildHandler waitpid of %d failed: %d (%s)", - childPid, res, strerror(errno)); - } else { - LOGW("setChildHandler waitpid of %d said %d already dead", - childPid, res); - } - - // Some kind of error... just handle the exit now. - self->mLock.unlock(); - - if (handler) { - handler(childPid, userData); - } - - // Return an error code -- 0 means it already exited. - return (status_t)res; - } - - ChildHandler entry; - entry.childPid = childPid; - entry.tag = tag; - entry.handler = handler; - entry.userData = userData; - - // Note: this replaces an existing entry for this pid, if there already - // is one. This is the required behavior. - LOGD("setChildHandler adding pid %d, tag %d, handler %p, data %p", - childPid, tag, handler, userData); - self->mChildHandlers.add(childPid, entry); - - self->mLock.unlock(); - - return NO_ERROR; -} - -void SignalHandler::killAllChildren(int tag) -{ - SignalHandler* const self = getInstance(); - - AutoMutex _l (self->mLock); - const size_t N = self->mChildHandlers.size(); - for (size_t i=0; i<N; i++) { - const ChildHandler& ch(self->mChildHandlers.valueAt(i)); - if (tag == 0 || ch.tag == tag) { - const pid_t pid = ch.childPid; - LOGI("Killing child %d (tag %d)\n", pid, ch.tag); - kill(pid, SIGKILL); - } - } -} - -SignalHandler::SignalHandler() - : mCommandTop(0) - , mCommandBottom(0) - , mLostCommands(0) -{ - memset(mCommands, 0, sizeof(mCommands)); - - int res = pipe(mAvailMsg); - LOGE_IF(res != 0, "Unable to create signal handler pipe: %s", strerror(errno)); - - mProcessThread = new ProcessThread(*this); - mProcessThread->run("SignalHandler", PRIORITY_HIGHEST); - - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_sigaction = sigAction; - sa.sa_flags = SA_NOCLDSTOP|SA_SIGINFO; - sigaction(SIGCHLD, &sa, NULL); -} - -SignalHandler::~SignalHandler() -{ -} - -SignalHandler* SignalHandler::getInstance() -{ - AutoMutex _l(mInstanceLock); - if (mInstance == NULL) { - mInstance = new SignalHandler(); - } - return mInstance; -} - -void SignalHandler::sigAction(int signum, siginfo_t* info, void*) -{ - static const char wakeupMsg[1] = { 0xff }; - - // If our signal handler is being called, then we know we have - // already initialized the SignalHandler class and thus mInstance - // is valid. - SignalHandler* const self = mInstance; - - // XXX This is not safe! - #if 0 - LOGV("Signal %d: signo=%d, errno=%d, code=%d, pid=%d\n", - signum, - info->si_signo, info->si_errno, info->si_code, - info->si_pid); - #endif - - int32_t oldTop, newTop; - - // Find the next command slot... - do { - oldTop = self->mCommandTop; - - newTop = oldTop + 1; - if (newTop >= COMMAND_QUEUE_SIZE) { - newTop = 0; - } - - if (newTop == self->mCommandBottom) { - // The buffer is filled up! Ouch! - // XXX This is not safe! - #if 0 - LOGE("Command buffer overflow! newTop=%d\n", newTop); - #endif - android_atomic_add(1, &self->mLostCommands); - write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg)); - return; - } - } while(android_atomic_cmpxchg(oldTop, newTop, &(self->mCommandTop))); - - // Fill in the command data... - self->mCommands[oldTop].signum = signum; - self->mCommands[oldTop].info = *info; - - // And now make this command available. - self->mCommands[oldTop].filled = 1; - - // Wake up the processing thread. - write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg)); -} - -}; // namespace android - |