Home | History | Annotate | Download | only in runtime
      1 //
      2 // Copyright 2005 The Android Open Source Project
      3 //
      4 #ifndef ANDROID_SIGNAL_HANDLER_H
      5 #define ANDROID_SIGNAL_HANDLER_H
      6 
      7 #include <utils/KeyedVector.h>
      8 #include <utils/threads.h>
      9 
     10 #include <signal.h>
     11 
     12 namespace android {
     13 
     14 // ----------------------------------------------------------------------
     15 
     16 enum {
     17     DEFAULT_PROCESS_TAG = 1
     18 };
     19 
     20 class SignalHandler
     21 {
     22 public:
     23     typedef void (*child_callback_t)(pid_t child, void* userData);
     24 
     25     /**
     26      * Set a handler for when a child process exits.  By calling
     27      * this, a waitpid() will be done when the child exits to remove
     28      * it from the zombie state.  You can also optionally specify a
     29      * handler to be called when the child exits.
     30      *
     31      * If there is already a handler for this child process, it is
     32      * replaced by this new handler.  In this case the old handler's
     33      * function is not called.
     34      *
     35      * @param childPid Process ID of child to watch.
     36      * @param childTag User-defined tag for this child.  Must be
     37      *                 greater than zero.
     38      * @param handler If non-NULL, this will be called when the
     39      *                child exits.  It may be called in either a
     40      *                separate signal handling thread, or
     41      *                immediately if the child has already exited.
     42      * @param userData Propageted as-is to handler.
     43      *
     44      * @return status_t NO_ERROR if all is well.
     45      */
     46     static status_t             setChildHandler(pid_t childPid,
     47                                                 int childTag = DEFAULT_PROCESS_TAG,
     48                                                 child_callback_t handler = NULL,
     49                                                 void* userData = NULL);
     50 
     51     /**
     52      * Kill all of the child processes for which we have a waiting
     53      * handler, whose tag is the given value.  If tag is 0, all
     54      * children are killed.
     55      *
     56      * @param tag
     57      */
     58     static void                 killAllChildren(int tag = 0);
     59 
     60 private:
     61                                 SignalHandler();
     62                                 ~SignalHandler();
     63 
     64     static SignalHandler*       getInstance();
     65 
     66     static void                 sigAction(int, siginfo_t*, void*);
     67 
     68     // --------------------------------------------------
     69     // Shared state...  all of this is protected by mLock.
     70     // --------------------------------------------------
     71 
     72     mutable Mutex                       mLock;
     73 
     74     struct ChildHandler
     75     {
     76         pid_t childPid;
     77         int tag;
     78         child_callback_t handler;
     79         void* userData;
     80     };
     81     KeyedVector<pid_t, ChildHandler>    mChildHandlers;
     82 
     83     // --------------------------------------------------
     84     // Commmand queue...  data is inserted by the signal
     85     // handler using atomic ops, and retrieved by the
     86     // signal processing thread.  Because these are touched
     87     // by the signal handler, no lock is used.
     88     // --------------------------------------------------
     89 
     90     enum {
     91         COMMAND_QUEUE_SIZE = 64
     92     };
     93     struct CommandEntry
     94     {
     95         int filled;
     96         int signum;
     97         siginfo_t info;
     98     };
     99 
    100     // The top of the queue.  This is incremented atomically by the
    101     // signal handler before placing a command in the queue.
    102     volatile int32_t                    mCommandTop;
    103 
    104     // The bottom of the queue.  Only modified by the processing
    105     // thread; the signal handler reads it only to determine if the
    106     // queue is full.
    107     int32_t                             mCommandBottom;
    108 
    109     // Incremented each time we receive a signal and don't have room
    110     // for it on the command queue.
    111     volatile int32_t                    mLostCommands;
    112 
    113     // The command processing thread.
    114     class ProcessThread;
    115     sp<Thread>                          mProcessThread;
    116 
    117     // Pipe used to tell command processing thread when new commands.
    118     // are available.  The thread blocks on the read end, the signal
    119     // handler writes when it enqueues new commands.
    120     int                                 mAvailMsg[2];
    121 
    122     // The commands.
    123     CommandEntry                        mCommands[COMMAND_QUEUE_SIZE];
    124 
    125     // --------------------------------------------------
    126     // Singleton.
    127     // --------------------------------------------------
    128 
    129     static Mutex                        mInstanceLock;
    130     static SignalHandler*               mInstance;
    131 };
    132 
    133 // ----------------------------------------------------------------------
    134 
    135 }; // namespace android
    136 
    137 #endif // ANDROID_SIGNAL_HANDLER_H
    138