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