mirror of
https://github.com/zeromq/libzmq.git
synced 2024-12-12 18:40:27 +01:00
Merge pull request #1138 from ewen-naos-nz/zos
z/OS UNIX System Services port: EAGAIN, SIGPIPE
This commit is contained in:
commit
57a70d5e3b
@ -43,24 +43,23 @@ installed, ZeroMQ can be built as follows:
|
||||
cd zeromq-VERSION
|
||||
builds/zos/makelibzmq
|
||||
|
||||
or to skip the `libzmq.so` dynamic library:
|
||||
or to skip the `libzmq.so` dynamic library (only building `libzmq.a`):
|
||||
|
||||
cd zeromq-VERSION
|
||||
BUILD_DLL=false
|
||||
export BUILD_DLL
|
||||
builds/zos/makelibzmq
|
||||
|
||||
* (Optional, but recommended) build the core tests with:
|
||||
* (Optional, but recommended) build and run the core tests with:
|
||||
|
||||
cd zeromq-VERSION
|
||||
builds/zos/maketests
|
||||
|
||||
* (Optional, but recommended) run the core tests:
|
||||
|
||||
builds/zos/runtests
|
||||
|
||||
* To remove built files, to start again (eg, rebuild with different
|
||||
compile/link flags):
|
||||
|
||||
cd zeromq-VERSION
|
||||
builds/zos/makeclean
|
||||
|
||||
There are details on specifying alternative compilation flags below.
|
||||
@ -89,7 +88,7 @@ Install `include/*.h` somewhere on your compiler include path.
|
||||
|
||||
Install `src/libzmq.so` somewhere on your LIBPATH.
|
||||
|
||||
Install `src/libzmq.x` somewhere you an reference for import linking.
|
||||
Install `src/libzmq.x` somewhere you can reference for import linking.
|
||||
|
||||
Compile and link application:
|
||||
|
||||
@ -98,10 +97,51 @@ Compile and link application:
|
||||
|
||||
Run with:
|
||||
|
||||
LIBPATH=/PATH/OF/LIBZMQ.SO:/lib:/usr/lib:... # if not in default path
|
||||
LIBPATH=/DIR/OF/LIBZMQ.SO:/lib:/usr/lib:... # if not in default path
|
||||
export LIBPATH
|
||||
./myprog
|
||||
|
||||
|
||||
## ZeroMQ on z/OS UNIX System Services: Application considerations
|
||||
|
||||
z/0S UNIX System Services does not provide a way to block the
|
||||
[`SIGPIPE` signal being generated when a thread writes to a closed socket](http://pic.dhe.ibm.com/infocenter/zvm/v6r2/index.jsp?topic=%2Fcom.ibm.zos.r12.cbcpx01%2Fcbcpg1b0287.htm)
|
||||
(compare with other platforms that support the `SO_NOSIGPIPE` socket
|
||||
option, and/or the `MSG_NOSIGNAL` flag on `send()`; z/OS UNIX System
|
||||
Services supports neither).
|
||||
|
||||
As a result, applications using ZeroMQ on z/OS UNIX System Services
|
||||
have to expect to encounter `SIGPIPE` at various times during the use
|
||||
of the library, if sockets are unexpectedly disconnected. Normally
|
||||
`SIGPIPE` will terminate the application.
|
||||
|
||||
A simple solution, if `SIGPIPE` is not required for normal operation
|
||||
of the application (eg, it is not part of a unix pipeline, the
|
||||
traditional use of `SIGPIPE`), is to set `SIGPIPE` to be ignored
|
||||
with code like:
|
||||
|
||||
#include <signal.h>
|
||||
...
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
near the start of the application (eg, before initialising the ZeroMQ
|
||||
library).
|
||||
|
||||
If `SIGPIPE` is required for normal operation it is recommended that
|
||||
the application install a signal handler that flags the signal was
|
||||
received, and allows the application main loop to determine if it
|
||||
was received for one of its own file descriptors -- and ignores it if it
|
||||
none of the applications own file descriptors seems to have changed.
|
||||
|
||||
Linking to the `libzmq.a` static library will pull in substantially
|
||||
all of the library code, which will add about 4MB to the application
|
||||
size (per executable statically linked with ZeroMQ). If this is a
|
||||
significant consideration, use of the DLL version is recommended.
|
||||
|
||||
See also ZeroMQ test status on z/OS UNIX System Services below
|
||||
for other caveats.
|
||||
|
||||
|
||||
## Setting other compilation flags
|
||||
|
||||
### Optimisation
|
||||
@ -152,38 +192,28 @@ pass. There are two tests that are expected to fail:
|
||||
pthreads both before *and* after fork. On z/OS (and some other
|
||||
UNIX compliant platforms) functions like `pthreads_create` (used
|
||||
by ZeroMQ) cannot be used after fork and before exec; on z/OS the
|
||||
call after fork fails with `ELEMULTITHREADFORK` (errno=257). (On
|
||||
z/OS it appears possible to use z/OS *after* fork, *providing* it
|
||||
has not been used before fork -- the problem is the two separate
|
||||
initialisations of the threading library before and after fork
|
||||
attempting to mix together.) In practice this is unlikely to
|
||||
affect many real-world programs -- most programs use threads or
|
||||
fork without exec, but not both.
|
||||
call after fork fails with `ELEMULTITHREADFORK` (errno=257) if
|
||||
ZeroMQ was also used before fork. (On z/OS it appears possible
|
||||
to use z/OS *after* fork, *providing* it has not been used before
|
||||
fork -- the problem is the two separate initialisations of the
|
||||
threading library, before and after fork, attempting to mix
|
||||
together.) In practice this is unlikely to affect many real-world
|
||||
programs -- most programs use threads or fork without exec, but
|
||||
not both.
|
||||
|
||||
These two "expected to fail" tests are listed as XFAIL_TESTS, and
|
||||
`runtests` will still consider the test run successful when they fail
|
||||
as expected.
|
||||
|
||||
In addition there are some other minor test issues:
|
||||
|
||||
* `test_security_curve` does not do any meaningful testing, as a
|
||||
result of the CURVE support not being compiled in; it requires
|
||||
In addition `test_security_curve` does not do any meaningful testing,
|
||||
as a result of the CURVE support not being compiled in; it requires
|
||||
[`libsodium`](http://doc.libsodium.org/), which has not been
|
||||
ported to z/OS UNIX System Services yet.
|
||||
|
||||
* Some tests will occassionally fail with `SIGPIPE` (about 1 run
|
||||
in 4 one of the tests will fail); this appears to be a problem
|
||||
with SIGPIPE not being ignored and has been reported upstream.
|
||||
The tests work fine if run again.
|
||||
|
||||
* Some tests will occassionally fail with `Resource temporarily
|
||||
unavailable`, which is a result of EAGAIN not being properly
|
||||
caught in all places and the function call retried. This has
|
||||
also been reported upstream. Again the tests work fine if
|
||||
run again.
|
||||
Multicast (via `libpgm`) is also not ported or compiled in.
|
||||
|
||||
|
||||
## ZeroMQ on z/OS UNIX System Services: Portability notes
|
||||
## ZeroMQ on z/OS UNIX System Services: Library portability notes
|
||||
|
||||
### *.cpp
|
||||
|
||||
@ -222,9 +252,9 @@ ago, and are required as part of the X/Open Portability Guide at least
|
||||
as of XPG 4.2. To access this functionality two feature macros are
|
||||
defined:
|
||||
|
||||
* _XOPEN_SOURCE_EXTENDED=1
|
||||
_XOPEN_SOURCE_EXTENDED=1
|
||||
|
||||
* _OPEN_SYS_SOCK_IPV6
|
||||
_OPEN_SYS_SOCK_IPV6
|
||||
|
||||
The first enables the XPG 4.2 features (including functionality like
|
||||
`getsockname()`), and the latter exposes IPv6 specific functionality
|
||||
@ -242,7 +272,7 @@ ZeroMQ uses the pthreads library to create additional threads to handle
|
||||
background communication without blocking the main application. This
|
||||
functionaity is enabled on z/OS UNIX System Services by defining:
|
||||
|
||||
* _OPEN_THREADS=3
|
||||
_OPEN_THREADS=3
|
||||
|
||||
which is done in the `cxxall` script. (The "3" value exposes later
|
||||
pthreads functionality like `pthread_atfork`, although ZeroMQ does not
|
||||
|
@ -62,6 +62,55 @@
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#if !defined (ZMQ_HAVE_WINDOWS)
|
||||
// Helper to sleep for specific number of milliseconds (or until signal)
|
||||
//
|
||||
static int sleep_ms (unsigned int ms_)
|
||||
{
|
||||
if (ms_ == 0)
|
||||
return 0;
|
||||
#if defined ZMQ_HAVE_WINDOWS
|
||||
Sleep (ms_ > 0 ? ms_ : INFINITE);
|
||||
return 0;
|
||||
#elif defined ZMQ_HAVE_ANDROID
|
||||
usleep (ms_ * 1000);
|
||||
return 0;
|
||||
#else
|
||||
return usleep (ms_ * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helper to wait on close(), for non-blocking sockets, until it completes
|
||||
// If EAGAIN is received, will sleep briefly (1-100ms) then try again, until
|
||||
// the overall timeout is reached.
|
||||
//
|
||||
static int close_wait_ms (int fd_, unsigned int max_ms_ = 2000)
|
||||
{
|
||||
unsigned int ms_so_far = 0;
|
||||
unsigned int step_ms = max_ms_ / 10;
|
||||
if (step_ms < 1)
|
||||
step_ms = 1;
|
||||
|
||||
if (step_ms > 100)
|
||||
step_ms = 100;
|
||||
|
||||
int rc = 0; // do not sleep on first attempt
|
||||
|
||||
do
|
||||
{
|
||||
if (rc == -1 && errno == EAGAIN)
|
||||
{
|
||||
sleep_ms (step_ms);
|
||||
ms_so_far += step_ms;
|
||||
}
|
||||
|
||||
rc = close (fd_);
|
||||
} while (ms_so_far < max_ms_ && rc == -1 && errno == EAGAIN);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
zmq::signaler_t::signaler_t ()
|
||||
{
|
||||
// Create the socketpair for signaling.
|
||||
@ -77,7 +126,7 @@ zmq::signaler_t::signaler_t ()
|
||||
zmq::signaler_t::~signaler_t ()
|
||||
{
|
||||
#if defined ZMQ_HAVE_EVENTFD
|
||||
int rc = close (r);
|
||||
int rc = close_wait_ms (r);
|
||||
errno_assert (rc == 0);
|
||||
#elif defined ZMQ_HAVE_WINDOWS
|
||||
const struct linger so_linger = { 1, 0 };
|
||||
@ -89,9 +138,9 @@ zmq::signaler_t::~signaler_t ()
|
||||
rc = closesocket (r);
|
||||
wsa_assert (rc != SOCKET_ERROR);
|
||||
#else
|
||||
int rc = close (w);
|
||||
int rc = close_wait_ms (w);
|
||||
errno_assert (rc == 0);
|
||||
rc = close (r);
|
||||
rc = close_wait_ms (r);
|
||||
errno_assert (rc == 0);
|
||||
#endif
|
||||
}
|
||||
|
@ -271,6 +271,11 @@ void setup_test_environment()
|
||||
// abort test after 60 seconds
|
||||
alarm(60);
|
||||
#endif
|
||||
#if defined __MVS__
|
||||
// z/OS UNIX System Services: Ignore SIGPIPE during test runs, as a
|
||||
// workaround for no SO_NOGSIGPIPE socket option.
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Provide portable millisecond sleep
|
||||
|
Loading…
Reference in New Issue
Block a user