summaryrefslogtreecommitdiffstats
path: root/cmds/runtime/SignalHandler.h
diff options
context:
space:
mode:
Diffstat (limited to 'cmds/runtime/SignalHandler.h')
-rw-r--r--cmds/runtime/SignalHandler.h137
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