138 lines
4.4 KiB
C++
138 lines
4.4 KiB
C++
//
|
|
// 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
|