From b6a07be5129e098b55c71d2d9cc11b14d3d86de9 Mon Sep 17 00:00:00 2001 From: Gudmundur Adalsteinsson Date: Tue, 2 Apr 2019 18:11:59 +0000 Subject: [PATCH] Problem: monitor_t incorrectly deletes socket_t move assignment operator Solution: Implement a move assignment operator for monitor_t --- tests/monitor.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ zmq.hpp | 26 +++++++++++++++++++------- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/tests/monitor.cpp b/tests/monitor.cpp index 9de1f6b..74a6d6a 100644 --- a/tests/monitor.cpp +++ b/tests/monitor.cpp @@ -33,6 +33,51 @@ TEST_CASE("monitor create destroy", "[monitor]") } #if defined(ZMQ_CPP11) +TEST_CASE("monitor move construct", "[monitor]") +{ + zmq::context_t ctx; + zmq::socket_t sock(ctx, ZMQ_DEALER); + SECTION("move ctor empty") + { + zmq::monitor_t monitor1; + zmq::monitor_t monitor2 = std::move(monitor1); + } + SECTION("move ctor init") + { + zmq::monitor_t monitor1; + monitor1.init(sock, "inproc://monitor-client"); + zmq::monitor_t monitor2 = std::move(monitor1); + } +} + +TEST_CASE("monitor move assign", "[monitor]") +{ + zmq::context_t ctx; + zmq::socket_t sock(ctx, ZMQ_DEALER); + SECTION("move assign empty") + { + zmq::monitor_t monitor1; + zmq::monitor_t monitor2; + monitor1 = std::move(monitor2); + } + SECTION("move assign init") + { + zmq::monitor_t monitor1; + monitor1.init(sock, "inproc://monitor-client"); + zmq::monitor_t monitor2; + monitor2 = std::move(monitor1); + } + SECTION("move assign init both") + { + zmq::monitor_t monitor1; + monitor1.init(sock, "inproc://monitor-client"); + zmq::monitor_t monitor2; + zmq::socket_t sock2(ctx, ZMQ_DEALER); + monitor2.init(sock2, "inproc://monitor-client2"); + monitor2 = std::move(monitor1); + } +} + TEST_CASE("monitor init event count", "[monitor]") { common_server_client_setup s{false}; diff --git a/zmq.hpp b/zmq.hpp index fc3b884..5bd5003 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -821,14 +821,9 @@ class monitor_t virtual ~monitor_t() { - if (socketPtr) - zmq_socket_monitor(socketPtr, ZMQ_NULLPTR, 0); - - if (monitor_socket) - zmq_close(monitor_socket); + close(); } - #ifdef ZMQ_HAS_RVALUE_REFS monitor_t(monitor_t &&rhs) ZMQ_NOTHROW : socketPtr(rhs.socketPtr), monitor_socket(rhs.monitor_socket) @@ -837,7 +832,15 @@ class monitor_t rhs.monitor_socket = ZMQ_NULLPTR; } - socket_t &operator=(socket_t &&rhs) ZMQ_DELETED_FUNCTION; + monitor_t &operator=(monitor_t &&rhs) ZMQ_NOTHROW + { + close(); + socketPtr = ZMQ_NULLPTR; + monitor_socket = ZMQ_NULLPTR; + std::swap(socketPtr, rhs.socketPtr); + std::swap(monitor_socket, rhs.monitor_socket); + return *this; + } #endif @@ -1113,6 +1116,15 @@ class monitor_t void *socketPtr; void *monitor_socket; + + void close() ZMQ_NOTHROW + { + if (socketPtr) + zmq_socket_monitor(socketPtr, ZMQ_NULLPTR, 0); + + if (monitor_socket) + zmq_close(monitor_socket); + } }; #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)