|  | // | 
|  | // 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 |