blob: 7f4ef8e4e8147c7c0ef75343b99ebb7e669f374d [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001//
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
12namespace android {
13
14// ----------------------------------------------------------------------
15
16enum {
17 DEFAULT_PROCESS_TAG = 1
18};
19
20class SignalHandler
21{
22public:
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
60private:
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