mirror of
https://github.com/zeromq/libzmq.git
synced 2024-12-27 07:31:03 +08:00
141 lines
4.8 KiB
Plaintext
141 lines
4.8 KiB
Plaintext
|
zmq_poll(3)
|
||
|
===========
|
||
|
|
||
|
|
||
|
NAME
|
||
|
----
|
||
|
zmq_ppoll - input/output multiplexing with signal mask
|
||
|
|
||
|
|
||
|
SYNOPSIS
|
||
|
--------
|
||
|
|
||
|
*int zmq_ppoll (zmq_pollitem_t '*items', int 'nitems', long 'timeout', const sigset_t '*sigmask');*
|
||
|
|
||
|
|
||
|
DESCRIPTION
|
||
|
-----------
|
||
|
The relationship between _zmq_poll()_ and _zmq_ppoll()_ is analogous to the
|
||
|
relationship between poll(2) and ppoll(2) and between select(2) and
|
||
|
pselect(2): _zmq_ppoll()_ allows an application to safely wait until either a
|
||
|
file descriptor becomes ready or until a signal is caught.
|
||
|
|
||
|
When using _zmq_ppoll()_ with 'sigmask' set to NULL, its behavior is identical
|
||
|
to that of _zmq_poll()_. See linkzmq:zmq_poll[3] for more on this.
|
||
|
|
||
|
To make full use of _zmq_ppoll()_, a non-NULL pointer to a signal mask must be
|
||
|
constructed and passed to 'sigmask'. See sigprocmask(2) for more details. When
|
||
|
this is done, inside the actual _ppoll()_ (or _pselect()_, see note below)
|
||
|
system call, an atomic operation consisting of three steps is performed:
|
||
|
1. The current signal mask is replaced by the one pointed to by 'sigmask'.
|
||
|
2. The actual _poll()_ call is done.
|
||
|
3. The original signal mask is restored.
|
||
|
Because these operations are done atomically, there is no opportunity for race
|
||
|
conditions in between the calls changing the signal mask and the poll/select
|
||
|
system call. This means that only during this (atomic) call, we can unblock
|
||
|
certain signals, so that they can be handled *at that time only*, not outside
|
||
|
of the call. This means that effectively, we extend our poller into a function
|
||
|
that not only watches sockets for changes, but also watches the "POSIX signal
|
||
|
socket" for incoming signals. At other times, these signals will be blocked,
|
||
|
and we will not have to deal with interruptions in system calls at these other
|
||
|
times.
|
||
|
|
||
|
NOTE: The _zmq_ppoll()_ function may be implemented or emulated using operating
|
||
|
system interfaces other than _ppoll()_, and as such may be subject to the
|
||
|
limits of those interfaces in ways not defined in this documentation.
|
||
|
|
||
|
NOTE: There is no _ppoll_ or _pselect_ on Windows, so _zmq_ppoll()_ is not
|
||
|
supported in Windows builds. It is still callable, but its 'sigmask' has void
|
||
|
pointer type (because 'sigset_t' is also not available on Windows) and
|
||
|
_zmq_ppoll()_ will return with an error (see error section below).
|
||
|
|
||
|
THREAD SAFETY
|
||
|
-------------
|
||
|
The *zmq_pollitem_t* array must only be used by the thread which
|
||
|
will/is calling _zmq_ppoll_.
|
||
|
|
||
|
If a socket is contained in multiple *zmq_pollitem_t* arrays, each owned by a
|
||
|
different thread, the socket itself needs to be thead-safe (Server, Client, ...).
|
||
|
Otherwise, behaviour is undefined.
|
||
|
|
||
|
|
||
|
RETURN VALUE
|
||
|
------------
|
||
|
Upon successful completion, the _zmq_ppoll()_ function shall return the number
|
||
|
of *zmq_pollitem_t* structures with events signaled in 'revents' or `0` if no
|
||
|
events have been signaled. Upon failure, _zmq_ppoll()_ shall return `-1` and set
|
||
|
'errno' to one of the values defined below.
|
||
|
|
||
|
|
||
|
ERRORS
|
||
|
------
|
||
|
*ETERM*::
|
||
|
At least one of the members of the 'items' array refers to a 'socket' whose
|
||
|
associated 0MQ 'context' was terminated.
|
||
|
*EFAULT*::
|
||
|
The provided 'items' was not valid (NULL).
|
||
|
*EINTR*::
|
||
|
The operation was interrupted by delivery of a signal before any events were
|
||
|
available.
|
||
|
*EINTR*::
|
||
|
The operation was interrupted by delivery of a signal before any events were
|
||
|
available.
|
||
|
*ENOTSUP*::
|
||
|
_zmq_ppoll()_ was not activated in this build.
|
||
|
|
||
|
|
||
|
EXAMPLE
|
||
|
-------
|
||
|
.Polling indefinitely for input events on both a 0MQ socket and a standard socket.
|
||
|
See the _example section_ of linkzmq:zmq_poll[3]. One only needs to replace
|
||
|
the _zmq_poll_ call with _zmq_ppoll_ and add a _NULL_ argument for the 'sigmask'
|
||
|
parameter.
|
||
|
|
||
|
.Handle SIGTERM during _zmq_ppoll_ (and block it otherwise).
|
||
|
----
|
||
|
// simple global signal handler for SIGTERM
|
||
|
static bool sigterm_received = false;
|
||
|
void handle_sigterm (int signum) {
|
||
|
sigterm_received = true;
|
||
|
}
|
||
|
|
||
|
// set up signal mask and install handler for SIGTERM
|
||
|
sigset_t sigmask, sigmask_without_sigterm;
|
||
|
sigemptyset(&sigmask);
|
||
|
sigaddset(&sigmask, SIGTERM);
|
||
|
sigprocmask(SIG_BLOCK, &sigmask, &sigmask_without_sigterm);
|
||
|
struct sigaction sa;
|
||
|
memset(&sa, '\0', sizeof(sa));
|
||
|
sa.sa_handler = handle_sigterm;
|
||
|
|
||
|
// poll
|
||
|
zmq_pollitem_t items [1];
|
||
|
// Just one item, which refers to 0MQ socket 'socket' */
|
||
|
items[0].socket = socket;
|
||
|
items[0].events = ZMQ_POLLIN;
|
||
|
// Poll for events indefinitely, but also exit on SIGTERM
|
||
|
int rc = zmq_poll (items, 2, -1, &sigmask_without_sigterm);
|
||
|
if (rc < 0 && errno == EINTR && sigterm_received) {
|
||
|
// do your SIGTERM business
|
||
|
} else {
|
||
|
// do your non-SIGTERM error handling
|
||
|
}
|
||
|
----
|
||
|
|
||
|
|
||
|
SEE ALSO
|
||
|
--------
|
||
|
linkzmq:zmq_poll[3]
|
||
|
linkzmq:zmq_socket[3]
|
||
|
linkzmq:zmq_send[3]
|
||
|
linkzmq:zmq_recv[3]
|
||
|
linkzmq:zmq[7]
|
||
|
|
||
|
Your operating system documentation for the _poll()_ system call.
|
||
|
|
||
|
|
||
|
AUTHORS
|
||
|
-------
|
||
|
This page was written by the 0MQ community. To make a change please
|
||
|
read the 0MQ Contribution Policy at <http://www.zeromq.org/docs:contributing>.
|