Skip to content

Commit 47969cf

Browse files
gummifsigiesec
authored andcommitted
Problem: shutdown() missing for context_t (#377)
Solution: Add shutdown(). This function is required for clean termination of the zmq context in multi-threaded applications where sockets are used in threads. In particular if blocking operation are used and if sockets can be created at any time. * Improve tests and documentation
1 parent 70d059b commit 47969cf

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

tests/context.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,25 @@ TEST_CASE("context create, close and destroy", "[context]")
1818
CHECK(NULL == (void *) context);
1919
}
2020

21+
TEST_CASE("context shutdown", "[context]")
22+
{
23+
zmq::context_t context;
24+
context.shutdown();
25+
CHECK(NULL != (void *) context);
26+
context.close();
27+
CHECK(NULL == (void *) context);
28+
}
29+
30+
TEST_CASE("context shutdown again", "[context]")
31+
{
32+
zmq::context_t context;
33+
context.shutdown();
34+
context.shutdown();
35+
CHECK(NULL != (void *) context);
36+
context.close();
37+
CHECK(NULL == (void *) context);
38+
}
39+
2140
#ifdef ZMQ_CPP11
2241
TEST_CASE("context swap", "[context]")
2342
{
@@ -26,4 +45,22 @@ TEST_CASE("context swap", "[context]")
2645
using std::swap;
2746
swap(context1, context2);
2847
}
48+
49+
TEST_CASE("context - use socket after shutdown", "[context]")
50+
{
51+
zmq::context_t context;
52+
zmq::socket_t sock(context, zmq::socket_type::rep);
53+
context.shutdown();
54+
try
55+
{
56+
sock.connect("inproc://test");
57+
zmq::message_t msg;
58+
sock.recv(msg, zmq::recv_flags::dontwait);
59+
REQUIRE(false);
60+
}
61+
catch (const zmq::error_t& e)
62+
{
63+
REQUIRE(e.num() == ETERM);
64+
}
65+
}
2966
#endif

zmq.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,7 @@ class context_t
677677

678678
~context_t() ZMQ_NOTHROW { close(); }
679679

680+
// Terminates context (see also shutdown()).
680681
void close() ZMQ_NOTHROW
681682
{
682683
if (ptr == ZMQ_NULLPTR)
@@ -691,6 +692,17 @@ class context_t
691692
ptr = ZMQ_NULLPTR;
692693
}
693694

695+
// Shutdown context in preparation for termination (close()).
696+
// Causes all blocking socket operations and any further
697+
// socket operations to return with ETERM.
698+
void shutdown() ZMQ_NOTHROW
699+
{
700+
if (ptr == ZMQ_NULLPTR)
701+
return;
702+
int rc = zmq_ctx_shutdown(ptr);
703+
ZMQ_ASSERT(rc == 0);
704+
}
705+
694706
// Be careful with this, it's probably only useful for
695707
// using the C api together with an existing C++ api.
696708
// Normally you should never need to use this.

0 commit comments

Comments
 (0)