diff --git a/doc/zmq_bind.txt b/doc/zmq_bind.txt index 23c31345..da20d78c 100644 --- a/doc/zmq_bind.txt +++ b/doc/zmq_bind.txt @@ -56,8 +56,8 @@ The requested 'address' was not local. The requested 'address' specifies a nonexistent interface. *ETERM*:: The 0MQ 'context' associated with the specified 'socket' was terminated. -*EFAULT*:: -The provided 'socket' was not valid (NULL). +*ENOTSOCK*:: +The provided 'socket' was invalid. *EMTHREAD*:: No I/O thread is available to accomplish the task. diff --git a/doc/zmq_close.txt b/doc/zmq_close.txt index fe3bde5e..9f026a36 100644 --- a/doc/zmq_close.txt +++ b/doc/zmq_close.txt @@ -34,8 +34,8 @@ return `-1` and set 'errno' to one of the values defined below. ERRORS ------ -*EFAULT*:: -The provided 'socket' was not valid (NULL). +*ENOTSOCK*:: +The provided 'socket' was invalid. SEE ALSO diff --git a/doc/zmq_connect.txt b/doc/zmq_connect.txt index a95f7167..d25270f2 100644 --- a/doc/zmq_connect.txt +++ b/doc/zmq_connect.txt @@ -54,8 +54,8 @@ The requested 'transport' protocol is not supported. The requested 'transport' protocol is not compatible with the socket type. *ETERM*:: The 0MQ 'context' associated with the specified 'socket' was terminated. -*EFAULT*:: -The provided 'socket' was not valid (NULL). +*ENOTSOCK*:: +The provided 'socket' was invalid. *EMTHREAD*:: No I/O thread is available to accomplish the task. diff --git a/doc/zmq_getsockopt.txt b/doc/zmq_getsockopt.txt index c5dd9682..926cf322 100644 --- a/doc/zmq_getsockopt.txt +++ b/doc/zmq_getsockopt.txt @@ -359,8 +359,8 @@ _option_value_, as specified by _option_len_, is insufficient for storing the option value. *ETERM*:: The 0MQ 'context' associated with the specified 'socket' was terminated. -*EFAULT*:: -The provided 'socket' was not valid (NULL). +*ENOTSOCK*:: +The provided 'socket' was invalid. *EINTR*:: The operation was interrupted by delivery of a signal. diff --git a/doc/zmq_recv.txt b/doc/zmq_recv.txt index 1588c646..fe601ba3 100644 --- a/doc/zmq_recv.txt +++ b/doc/zmq_recv.txt @@ -63,8 +63,8 @@ socket types that switch between several states, such as ZMQ_REP. See the _messaging patterns_ section of linkzmq:zmq_socket[3] for more information. *ETERM*:: The 0MQ 'context' associated with the specified 'socket' was terminated. -*EFAULT*:: -The provided 'socket' was not valid (NULL). +*ENOTSOCK*:: +The provided 'socket' was invalid. *EINTR*:: The operation was interrupted by delivery of a signal before a message was available. diff --git a/doc/zmq_send.txt b/doc/zmq_send.txt index c8d6f33d..4561ae03 100644 --- a/doc/zmq_send.txt +++ b/doc/zmq_send.txt @@ -69,8 +69,8 @@ socket types that switch between several states, such as ZMQ_REP. See the _messaging patterns_ section of linkzmq:zmq_socket[3] for more information. *ETERM*:: The 0MQ 'context' associated with the specified 'socket' was terminated. -*EFAULT*:: -The provided 'socket' was not valid (NULL). +*ENOTSOCK*:: +The provided 'socket' was invalid. *EINTR*:: The operation was interrupted by delivery of a signal before the message was sent. diff --git a/doc/zmq_setsockopt.txt b/doc/zmq_setsockopt.txt index 48afbfc6..f5c873ec 100644 --- a/doc/zmq_setsockopt.txt +++ b/doc/zmq_setsockopt.txt @@ -310,8 +310,8 @@ The requested option _option_name_ is unknown, or the requested _option_len_ or _option_value_ is invalid. *ETERM*:: The 0MQ 'context' associated with the specified 'socket' was terminated. -*EFAULT*:: -The provided 'socket' was not valid (NULL). +*ENOTSOCK*:: +The provided 'socket' was invalid. *EINTR*:: The operation was interrupted by delivery of a signal. diff --git a/doc/zmq_socket.txt b/doc/zmq_socket.txt index e8c42537..a319518f 100644 --- a/doc/zmq_socket.txt +++ b/doc/zmq_socket.txt @@ -309,7 +309,7 @@ ERRORS *EINVAL*:: The requested socket 'type' is invalid. *EFAULT*:: -The provided 'context' was not valid (NULL). +The provided 'context' is invalid. *ETERM*:: The context specified was terminated. diff --git a/doc/zmq_term.txt b/doc/zmq_term.txt index d3914dbe..64e32ca1 100644 --- a/doc/zmq_term.txt +++ b/doc/zmq_term.txt @@ -46,7 +46,7 @@ return `-1` and set 'errno' to one of the values defined below. ERRORS ------ *EFAULT*:: -The provided 'context' was not valid (NULL). +The provided 'context' was invalid. *EINTR*:: Termination was interrupted by a signal. It can be restarted if needed. diff --git a/src/ctx.cpp b/src/ctx.cpp index 9cbb9ded..27587295 100644 --- a/src/ctx.cpp +++ b/src/ctx.cpp @@ -36,6 +36,7 @@ #endif zmq::ctx_t::ctx_t (uint32_t io_threads_) : + tag (0xbadcafe0), terminating (false) { int rc; @@ -78,6 +79,11 @@ zmq::ctx_t::ctx_t (uint32_t io_threads_) : zmq_assert (rc == 0); } +bool zmq::ctx_t::check_tag () +{ + return tag == 0xbadcafe0; +} + zmq::ctx_t::~ctx_t () { // Check that there are no remaining sockets. @@ -99,6 +105,9 @@ zmq::ctx_t::~ctx_t () // needed as mailboxes themselves were deallocated with their // corresponding io_thread/socket objects. free (slots); + + // Remove the tag, so that the object is considered dead. + tag = 0xdeadbeef; } int zmq::ctx_t::terminate () diff --git a/src/ctx.hpp b/src/ctx.hpp index c6ea4ceb..33d5dadd 100644 --- a/src/ctx.hpp +++ b/src/ctx.hpp @@ -60,6 +60,9 @@ namespace zmq // of I/O thread pool to create. ctx_t (uint32_t io_threads_); + // Returns false if object is not a context. + bool check_tag (); + // This function is called when user invokes zmq_term. If there are // no more sockets open it'll cause all the infrastructure to be shut // down. If there are open sockets still, the deallocation happens @@ -98,6 +101,9 @@ namespace zmq ~ctx_t (); + // Used to check whether the object is a context. + uint32_t tag; + // Sockets belonging to this context. We need the list so that // we can notify the sockets when zmq_term() is called. The sockets // will return ETERM then. diff --git a/src/socket_base.cpp b/src/socket_base.cpp index b1d11428..c9b5c31e 100644 --- a/src/socket_base.cpp +++ b/src/socket_base.cpp @@ -61,6 +61,11 @@ #include "xpub.hpp" #include "xsub.hpp" +bool zmq::socket_base_t::check_tag () +{ + return tag == 0xbaddecaf; +} + zmq::socket_base_t *zmq::socket_base_t::create (int type_, class ctx_t *parent_, uint32_t tid_) { @@ -110,6 +115,7 @@ zmq::socket_base_t *zmq::socket_base_t::create (int type_, class ctx_t *parent_, zmq::socket_base_t::socket_base_t (ctx_t *parent_, uint32_t tid_) : own_t (parent_, tid_), + tag (0xbaddecaf), ctx_terminated (false), destroyed (false), last_tsc (0), @@ -126,6 +132,9 @@ zmq::socket_base_t::~socket_base_t () sessions_sync.lock (); zmq_assert (sessions.empty ()); sessions_sync.unlock (); + + // Mark the socket as dead. + tag = 0xdeadbeef; } zmq::mailbox_t *zmq::socket_base_t::get_mailbox () diff --git a/src/socket_base.hpp b/src/socket_base.hpp index 15ac83c2..333cddd2 100644 --- a/src/socket_base.hpp +++ b/src/socket_base.hpp @@ -50,6 +50,9 @@ namespace zmq public: + // Returns false if object is not a socket. + bool check_tag (); + // Create a socket of a specified type. static socket_base_t *create (int type_, class ctx_t *parent_, uint32_t tid_); @@ -136,6 +139,9 @@ namespace zmq private: + // Used to check whether the object is a socket. + uint32_t tag; + // If true, associated context was already terminated. bool ctx_terminated; diff --git a/src/zmq.cpp b/src/zmq.cpp index c65e1663..0f536ace 100644 --- a/src/zmq.cpp +++ b/src/zmq.cpp @@ -261,7 +261,7 @@ void *zmq_init (int io_threads_) int zmq_term (void *ctx_) { - if (!ctx_) { + if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) { errno = EFAULT; return -1; } @@ -287,7 +287,7 @@ int zmq_term (void *ctx_) void *zmq_socket (void *ctx_, int type_) { - if (!ctx_) { + if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) { errno = EFAULT; return NULL; } @@ -296,8 +296,8 @@ void *zmq_socket (void *ctx_, int type_) int zmq_close (void *s_) { - if (!s_) { - errno = EFAULT; + if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { + errno = ENOTSOCK; return -1; } ((zmq::socket_base_t*) s_)->close (); @@ -307,8 +307,8 @@ int zmq_close (void *s_) int zmq_setsockopt (void *s_, int option_, const void *optval_, size_t optvallen_) { - if (!s_) { - errno = EFAULT; + if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { + errno = ENOTSOCK; return -1; } return (((zmq::socket_base_t*) s_)->setsockopt (option_, optval_, @@ -317,8 +317,8 @@ int zmq_setsockopt (void *s_, int option_, const void *optval_, int zmq_getsockopt (void *s_, int option_, void *optval_, size_t *optvallen_) { - if (!s_) { - errno = EFAULT; + if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { + errno = ENOTSOCK; return -1; } return (((zmq::socket_base_t*) s_)->getsockopt (option_, optval_, @@ -327,8 +327,8 @@ int zmq_getsockopt (void *s_, int option_, void *optval_, size_t *optvallen_) int zmq_bind (void *s_, const char *addr_) { - if (!s_) { - errno = EFAULT; + if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { + errno = ENOTSOCK; return -1; } return (((zmq::socket_base_t*) s_)->bind (addr_)); @@ -336,8 +336,8 @@ int zmq_bind (void *s_, const char *addr_) int zmq_connect (void *s_, const char *addr_) { - if (!s_) { - errno = EFAULT; + if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { + errno = ENOTSOCK; return -1; } return (((zmq::socket_base_t*) s_)->connect (addr_)); @@ -393,8 +393,8 @@ int zmq_recv (void *s_, void *buf_, size_t len_, int flags_) int zmq_sendmsg (void *s_, zmq_msg_t *msg_, int flags_) { - if (!s_) { - errno = EFAULT; + if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { + errno = ENOTSOCK; return -1; } int sz = (int) zmq_msg_size (msg_); @@ -406,8 +406,8 @@ int zmq_sendmsg (void *s_, zmq_msg_t *msg_, int flags_) int zmq_recvmsg (void *s_, zmq_msg_t *msg_, int flags_) { - if (!s_) { - errno = EFAULT; + if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) { + errno = ENOTSOCK; return -1; } int rc = (((zmq::socket_base_t*) s_)->recv (msg_, flags_));