mirror of
https://github.com/zeromq/libzmq.git
synced 2025-03-12 17:12:46 +00:00
Merge pull request #3794 from sigiesec/fix-ctx-shutdown
Problem: sockets can be created after calling zmq_ctx_shutdown
This commit is contained in:
commit
6d69898240
@ -19,7 +19,9 @@ The _zmq_ctx_shutdown()_ function shall shutdown the 0MQ context 'context'.
|
|||||||
Context shutdown will cause any blocking operations currently in progress on
|
Context shutdown will cause any blocking operations currently in progress on
|
||||||
sockets open within 'context' to return immediately with an error code of ETERM.
|
sockets open within 'context' to return immediately with an error code of ETERM.
|
||||||
With the exception of _zmq_close()_, any further operations on sockets open within
|
With the exception of _zmq_close()_, any further operations on sockets open within
|
||||||
'context' shall fail with an error code of ETERM.
|
'context' shall fail with an error code of ETERM. No further sockets can be created
|
||||||
|
using _zmq_socket()_ on a context for which _zmq_ctx_shutdown()_ has been called,
|
||||||
|
it will return and set errno to ETERM.
|
||||||
|
|
||||||
This function is optional, client code is still required to call the linkzmq:zmq_ctx_term[3]
|
This function is optional, client code is still required to call the linkzmq:zmq_ctx_term[3]
|
||||||
function to free all resources allocated by zeromq.
|
function to free all resources allocated by zeromq.
|
||||||
|
@ -556,7 +556,7 @@ The provided 'context' is invalid.
|
|||||||
*EMFILE*::
|
*EMFILE*::
|
||||||
The limit on the total number of open 0MQ sockets has been reached.
|
The limit on the total number of open 0MQ sockets has been reached.
|
||||||
*ETERM*::
|
*ETERM*::
|
||||||
The context specified was terminated.
|
The context specified was shutdown or terminated.
|
||||||
|
|
||||||
EXAMPLE
|
EXAMPLE
|
||||||
-------
|
-------
|
||||||
|
31
src/ctx.cpp
31
src/ctx.cpp
@ -232,16 +232,18 @@ int zmq::ctx_t::shutdown ()
|
|||||||
{
|
{
|
||||||
scoped_lock_t locker (_slot_sync);
|
scoped_lock_t locker (_slot_sync);
|
||||||
|
|
||||||
if (!_starting && !_terminating) {
|
if (!_terminating) {
|
||||||
_terminating = true;
|
_terminating = true;
|
||||||
|
|
||||||
// Send stop command to sockets so that any blocking calls
|
if (!_starting) {
|
||||||
// can be interrupted. If there are no sockets we can ask reaper
|
// Send stop command to sockets so that any blocking calls
|
||||||
// thread to stop.
|
// can be interrupted. If there are no sockets we can ask reaper
|
||||||
for (sockets_t::size_type i = 0; i != _sockets.size (); i++)
|
// thread to stop.
|
||||||
_sockets[i]->stop ();
|
for (sockets_t::size_type i = 0; i != _sockets.size (); i++)
|
||||||
if (_sockets.empty ())
|
_sockets[i]->stop ();
|
||||||
_reaper->stop ();
|
if (_sockets.empty ())
|
||||||
|
_reaper->stop ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -471,17 +473,18 @@ zmq::socket_base_t *zmq::ctx_t::create_socket (int type_)
|
|||||||
{
|
{
|
||||||
scoped_lock_t locker (_slot_sync);
|
scoped_lock_t locker (_slot_sync);
|
||||||
|
|
||||||
if (unlikely (_starting)) {
|
// Once zmq_ctx_term() or zmq_ctx_shutdown() was called, we can't create
|
||||||
if (!start ())
|
// new sockets.
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Once zmq_ctx_term() was called, we can't create new sockets.
|
|
||||||
if (_terminating) {
|
if (_terminating) {
|
||||||
errno = ETERM;
|
errno = ETERM;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely (_starting)) {
|
||||||
|
if (!start ())
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// If max_sockets limit was reached, return error.
|
// If max_sockets limit was reached, return error.
|
||||||
if (_empty_slots.empty ()) {
|
if (_empty_slots.empty ()) {
|
||||||
errno = EMFILE;
|
errno = EMFILE;
|
||||||
|
@ -88,7 +88,46 @@ void test_ctx_shutdown ()
|
|||||||
// Close the socket.
|
// Close the socket.
|
||||||
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
|
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
|
||||||
|
|
||||||
// Destory the context, will now not hang as we have closed the socket.
|
// Destroy the context, will now not hang as we have closed the socket.
|
||||||
|
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_destroy (ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ctx_shutdown_socket_opened_after ()
|
||||||
|
{
|
||||||
|
// Set up our context.
|
||||||
|
void *ctx = zmq_ctx_new ();
|
||||||
|
TEST_ASSERT_NOT_NULL (ctx);
|
||||||
|
|
||||||
|
// Open a socket to start context, and close it immediately again.
|
||||||
|
void *socket = zmq_socket (ctx, ZMQ_PULL);
|
||||||
|
TEST_ASSERT_NOT_NULL (socket);
|
||||||
|
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
|
||||||
|
|
||||||
|
// Shutdown context.
|
||||||
|
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_shutdown (ctx));
|
||||||
|
|
||||||
|
// Opening socket should now fail.
|
||||||
|
TEST_ASSERT_NULL (zmq_socket (ctx, ZMQ_PULL));
|
||||||
|
TEST_ASSERT_FAILURE_ERRNO (ETERM, -1);
|
||||||
|
|
||||||
|
// Destroy the context.
|
||||||
|
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_destroy (ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ctx_shutdown_only_socket_opened_after ()
|
||||||
|
{
|
||||||
|
// Set up our context.
|
||||||
|
void *ctx = zmq_ctx_new ();
|
||||||
|
TEST_ASSERT_NOT_NULL (ctx);
|
||||||
|
|
||||||
|
// Shutdown context.
|
||||||
|
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_shutdown (ctx));
|
||||||
|
|
||||||
|
// Opening socket should now fail.
|
||||||
|
TEST_ASSERT_NULL (zmq_socket (ctx, ZMQ_PULL));
|
||||||
|
TEST_ASSERT_FAILURE_ERRNO (ETERM, -1);
|
||||||
|
|
||||||
|
// Destroy the context.
|
||||||
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_destroy (ctx));
|
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_destroy (ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,6 +240,8 @@ int main (void)
|
|||||||
UNITY_BEGIN ();
|
UNITY_BEGIN ();
|
||||||
RUN_TEST (test_ctx_destroy);
|
RUN_TEST (test_ctx_destroy);
|
||||||
RUN_TEST (test_ctx_shutdown);
|
RUN_TEST (test_ctx_shutdown);
|
||||||
|
RUN_TEST (test_ctx_shutdown_socket_opened_after);
|
||||||
|
RUN_TEST (test_ctx_shutdown_only_socket_opened_after);
|
||||||
RUN_TEST (test_zmq_ctx_term_null_fails);
|
RUN_TEST (test_zmq_ctx_term_null_fails);
|
||||||
RUN_TEST (test_zmq_term_null_fails);
|
RUN_TEST (test_zmq_term_null_fails);
|
||||||
RUN_TEST (test_zmq_ctx_shutdown_null_fails);
|
RUN_TEST (test_zmq_ctx_shutdown_null_fails);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user