int pmLoopRegisterChild(pid_t pid,
int (*callback)(pid_t pid, int status, const struct rusage *rusage, void *closure),
void *closure);
int pmLoopRegisterIdle(
int (*callback)(void *closure),
void *closure);
int pmLoopRegisterInput(int fd, int flags,
int (*callback)(int fd, int flags, void *closure),
void *closure, int priority);
int pmLoopRegisterSignal(int sig,
int (*callback)(int sig, void *closure),
void *closure);
int pmLoopRegisterTimeout(int delay_msec,
int (*callback)(void *closure),
void *closure);
int pmLoopUnregisterChild(int tag);
int pmLoopUnregisterIdle(int tag);
int pmLoopUnregisterInput(int tag);
int pmLoopUnregisterSignal(int tag);
int pmLoopUnregisterTimeout(int tag);
void pmLoopStop(void);
void pmLoopMain(void);
cc ... -lpcp
DESCRIPTION
These functions implement a generic UNIX main poll(2) loop which
can be found at the heart of many UNIX daemon processes and a number
of the associated features which the UNIX process model requires
the same code to handle, for example timers and safe delivery of
signals. Inspiration for this module came from (in chronological order)
the SunView notifier library, the X Intrinsics Toolkit main loop,
and the GTK+/libglib main loop feature.
The module supports the following features:
*
callback to application code from main loop when
input or output is possible on a file descriptor
*
callback when a (catchable) signal is delivered
*
callback on a timeout, including recurring timeouts
*
callback when a child process has died (or its status
is otherwise notified via wait3(2)).
*
callback when the main loop is idle
*
all callbacks occur at safe times, e.g. signal callback
occurs when main loop is idle and not partway through
another callback.
*
a callback is automatically unregisted if the callback's function returns
non-zero value.
*
application code can call a subsidiary main loop, to
handle and dispatch all registered callbacks for
some time without returning to the main loop.
int pmLoopRegisterInput(int fd, int flags,
int (*callback)(int fd, int flags, void *closure),
void *closure, int priority);
Register callback to be called when input or output becomes
possible on file descriptor fd. The flags are a bitmask of
poll(2) flags, e.g. POLLIN will cause the callback to be called
when input is available on the file descriptor and POLLOUT is
for when output becomes possible. The closure pointer is
not interpreted in any way, but is passed to the callback; the
application may use this to pass around a pointer to any data
it needs. Priority may be used to force the order of dispatch
of callbacks when multiple file descriptors become available
at the same time; callbacks are dispatched in increasing order
of their priority number. The return value is a tag which is
unique amongst all registered callbacks (e.g. registering the
same callback twice gives two different tags) and which can be
used to remove the callback using pmLoopUnregisterInput().
void pmLoopUnregisterInput(int tag);
Unregisters a file descriptor input callback previously registered
with pmLoopRegisterInput(). This can safely be called from within
the callback being deregistered.
int pmLoopRegisterSignal(int sig,
int (*callback)(int sig, void *closure),
void *closure);
Register callback to be called when signal sig is
delivered to the process. Some signals cannot be caught,
see the signal(7) manpage for details. Catching SIGCHLD is
not recommended, see pmLoopRegisterChild() for a better way to
detect child process status changes. The closure pointer is
not interpreted in any way, but is passed to the callback; the
application may use this to pass around a pointer to any data
it needs. The return value is a tag which is unique amongst
all registered callbacks (e.g. registering the same callback
twice gives two different tags) and which can be used to remove
the callback using pmLoopUnregisterSignal(). Once registered,
a callback stays registered unless explicitly unregistered with
pmLoopUnregisterSignal(), and does not need to be re-registered
after a signal is delivered. Note that two or more callbacks
can be registered for the same signal; they are dispatched in
the reverse of the order in which they were registered.
void pmLoopUnregisterSignal(int tag);
Unregisters a signal callback previously registered with
pmLoopRegisterSignal(). This can safely be called from within
the callback being deregistered.
int pmLoopRegisterTimeout(int delay_msec,
int (*callback)(void *closure),
void *closure);
Register callback to be called after delay_msec milliseconds
have elapsed. If delay is 0, the callback is called immediately.
The closure pointer is not interpreted in any way, but is passed
to the callback; the application may use this to pass around a pointer
to any data it needs. The return value is a tag which is unique amongst
all registered callbacks (e.g. registering the same callback twice gives
two different tags) and which can be used to remove the callback using
pmLoopUnregisterTimeout(). Once registered, a callback stays registered
until it is either explictly unregisterd or the callback function returns
non-zero value.
void pmLoopUnregisterTimeout(int tag);
Unregisters a timeout callback previously registered with
pmLoopRegisterTimeout(). This can safely be called from within
the callback being deregistered.
int pmLoopRegisterChild(pid_t pid,
int (*callback)(pid_t pid, int status, const struct rusage *rusage, void * closure),
void *closure);
Register callback to be called when the child process pid
changes status in a way which triggers a wait3(2) notification.
Normally, this means the process has called exit() or died in
some other manner, but see the wait3(2) manpage. Waiting on a
process group (e.g. by passing a negative pid) is not supported.
All descendant processes started by the process will be reaped by
the module, regardless of whether a child process callback
has been registered for them or not. The status and rusage
argument to the callback are from the wait3(2) system call, see
the wait3(2) manpage for how to use the macros WIFSTOPPED() et al
to interpret these. The closure pointer is not interpreted
in any way, but is passed to the callback; the application
may use this to pass around a pointer to any data it needs.
The return value is a tag which is unique amongst all registered
callbacks (e.g. registering the same callback twice gives two
different tags) and which can be used to remove the callback
using pmLoopUnregisterChild(). Once registered, a callback is
automatically unregistered if status indicates that the process
has died (this is the usual case), otherwise it stays registered.
void pmLoopUnregisterChild(int tag);
Unregisters a child process callback previously registered with
pmLoopRegisterChild(). This can safely be called from within
the callback being deregistered.
int pmLoopRegisterIdle(
int (*callback)(void *closure),
void *closure);
Register callback to be called whenever the loop module is idle,
i.e. no other callbacks are pending. This is useful for doing
background processing while still responding to other events.
Note that the callback function can be called many thousands
of times per second, so this feature should be used with care.
The closure pointer is not interpreted in any way, but is passed
to the callback; the application may use this to pass around a
pointer to any data it needs. The return value is a tag which
is unique amongst all registered callbacks (e.g. registering
the same callback twice gives two different tags) and which can
be used to remove the callback using pmLoopUnregisterIdle().
Once registered, a callback stays registered.
void pmLoopUnregisterIdle(int tag);
Unregisters a child process callback previously registered with
pmLoopRegisterIdle(). This can safely be called from within
the callback being deregistered.
void pmLoopMain(void);
This function starts the main loop of an application. It handles
various UNIX events and dispatches registered callbacks, not
returning until pmLoopStop() is called.
Note that pmLoopMain() may be called in an callback, which
has the effect of running a subsidiary loop, i.e. loop for a
while handling events and dispatching callbacks as the main
loop would do, but without returning control to the main loop.
Such subsidiary loops can be nested.
void pmLoopStop(void);
Causes the innermost pmLoopMain() to return when it is next idle,
i.e. as soon as the current callback has returned.