diff options
Diffstat (limited to 'cmds/runtime/SignalHandler.h')
-rw-r--r-- | cmds/runtime/SignalHandler.h | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/cmds/runtime/SignalHandler.h b/cmds/runtime/SignalHandler.h new file mode 100644 index 0000000..7f4ef8e --- /dev/null +++ b/cmds/runtime/SignalHandler.h @@ -0,0 +1,137 @@ +// +// Copyright 2005 The Android Open Source Project +// +#ifndef ANDROID_SIGNAL_HANDLER_H +#define ANDROID_SIGNAL_HANDLER_H + +#include <utils/KeyedVector.h> +#include <utils/threads.h> + +#include <signal.h> + +namespace android { + +// ---------------------------------------------------------------------- + +enum { + DEFAULT_PROCESS_TAG = 1 +}; + +class SignalHandler +{ +public: + typedef void (*child_callback_t)(pid_t child, void* userData); + + /** + * Set a handler for when a child process exits. By calling + * this, a waitpid() will be done when the child exits to remove + * it from the zombie state. You can also optionally specify a + * handler to be called when the child exits. + * + * If there is already a handler for this child process, it is + * replaced by this new handler. In this case the old handler's + * function is not called. + * + * @param childPid Process ID of child to watch. + * @param childTag User-defined tag for this child. Must be + * greater than zero. + * @param handler If non-NULL, this will be called when the + * child exits. It may be called in either a + * separate signal handling thread, or + * immediately if the child has already exited. + * @param userData Propageted as-is to handler. + * + * @return status_t NO_ERROR if all is well. + */ + static status_t setChildHandler(pid_t childPid, + int childTag = DEFAULT_PROCESS_TAG, + child_callback_t handler = NULL, + void* userData = NULL); + + /** + * Kill all of the child processes for which we have a waiting + * handler, whose tag is the given value. If tag is 0, all + * children are killed. + * + * @param tag + */ + static void killAllChildren(int tag = 0); + +private: + SignalHandler(); + ~SignalHandler(); + + static SignalHandler* getInstance(); + + static void sigAction(int, siginfo_t*, void*); + + // -------------------------------------------------- + // Shared state... all of this is protected by mLock. + // -------------------------------------------------- + + mutable Mutex mLock; + + struct ChildHandler + { + pid_t childPid; + int tag; + child_callback_t handler; + void* userData; + }; + KeyedVector<pid_t, ChildHandler> mChildHandlers; + + // -------------------------------------------------- + // Commmand queue... data is inserted by the signal + // handler using atomic ops, and retrieved by the + // signal processing thread. Because these are touched + // by the signal handler, no lock is used. + // -------------------------------------------------- + + enum { + COMMAND_QUEUE_SIZE = 64 + }; + struct CommandEntry + { + int filled; + int signum; + siginfo_t info; + }; + + // The top of the queue. This is incremented atomically by the + // signal handler before placing a command in the queue. + volatile int32_t mCommandTop; + + // The bottom of the queue. Only modified by the processing + // thread; the signal handler reads it only to determine if the + // queue is full. + int32_t mCommandBottom; + + // Incremented each time we receive a signal and don't have room + // for it on the command queue. + volatile int32_t mLostCommands; + + // The command processing thread. + class ProcessThread; + sp<Thread> mProcessThread; + + // Pipe used to tell command processing thread when new commands. + // are available. The thread blocks on the read end, the signal + // handler writes when it enqueues new commands. + int mAvailMsg[2]; + + // The commands. + CommandEntry mCommands[COMMAND_QUEUE_SIZE]; + + // -------------------------------------------------- + // Singleton. + // -------------------------------------------------- + + static Mutex mInstanceLock; + static SignalHandler* mInstance; +}; + +// ---------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_SIGNAL_HANDLER_H |