• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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