Run-time checking for context & socket validity added

Signed-off-by: Martin Sustrik <sustrik@250bpm.com>
This commit is contained in:
Martin Sustrik 2011-04-09 09:35:34 +02:00
parent e62686aca5
commit b96fe15bb6
14 changed files with 62 additions and 32 deletions

View File

@ -56,8 +56,8 @@ The requested 'address' was not local.
The requested 'address' specifies a nonexistent interface. The requested 'address' specifies a nonexistent interface.
*ETERM*:: *ETERM*::
The 0MQ 'context' associated with the specified 'socket' was terminated. The 0MQ 'context' associated with the specified 'socket' was terminated.
*EFAULT*:: *ENOTSOCK*::
The provided 'socket' was not valid (NULL). The provided 'socket' was invalid.
*EMTHREAD*:: *EMTHREAD*::
No I/O thread is available to accomplish the task. No I/O thread is available to accomplish the task.

View File

@ -34,8 +34,8 @@ return `-1` and set 'errno' to one of the values defined below.
ERRORS ERRORS
------ ------
*EFAULT*:: *ENOTSOCK*::
The provided 'socket' was not valid (NULL). The provided 'socket' was invalid.
SEE ALSO SEE ALSO

View File

@ -54,8 +54,8 @@ The requested 'transport' protocol is not supported.
The requested 'transport' protocol is not compatible with the socket type. The requested 'transport' protocol is not compatible with the socket type.
*ETERM*:: *ETERM*::
The 0MQ 'context' associated with the specified 'socket' was terminated. The 0MQ 'context' associated with the specified 'socket' was terminated.
*EFAULT*:: *ENOTSOCK*::
The provided 'socket' was not valid (NULL). The provided 'socket' was invalid.
*EMTHREAD*:: *EMTHREAD*::
No I/O thread is available to accomplish the task. No I/O thread is available to accomplish the task.

View File

@ -359,8 +359,8 @@ _option_value_, as specified by _option_len_, is insufficient for storing the
option value. option value.
*ETERM*:: *ETERM*::
The 0MQ 'context' associated with the specified 'socket' was terminated. The 0MQ 'context' associated with the specified 'socket' was terminated.
*EFAULT*:: *ENOTSOCK*::
The provided 'socket' was not valid (NULL). The provided 'socket' was invalid.
*EINTR*:: *EINTR*::
The operation was interrupted by delivery of a signal. The operation was interrupted by delivery of a signal.

View File

@ -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. _messaging patterns_ section of linkzmq:zmq_socket[3] for more information.
*ETERM*:: *ETERM*::
The 0MQ 'context' associated with the specified 'socket' was terminated. The 0MQ 'context' associated with the specified 'socket' was terminated.
*EFAULT*:: *ENOTSOCK*::
The provided 'socket' was not valid (NULL). The provided 'socket' was invalid.
*EINTR*:: *EINTR*::
The operation was interrupted by delivery of a signal before a message was The operation was interrupted by delivery of a signal before a message was
available. available.

View File

@ -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. _messaging patterns_ section of linkzmq:zmq_socket[3] for more information.
*ETERM*:: *ETERM*::
The 0MQ 'context' associated with the specified 'socket' was terminated. The 0MQ 'context' associated with the specified 'socket' was terminated.
*EFAULT*:: *ENOTSOCK*::
The provided 'socket' was not valid (NULL). The provided 'socket' was invalid.
*EINTR*:: *EINTR*::
The operation was interrupted by delivery of a signal before the message was The operation was interrupted by delivery of a signal before the message was
sent. sent.

View File

@ -310,8 +310,8 @@ The requested option _option_name_ is unknown, or the requested _option_len_ or
_option_value_ is invalid. _option_value_ is invalid.
*ETERM*:: *ETERM*::
The 0MQ 'context' associated with the specified 'socket' was terminated. The 0MQ 'context' associated with the specified 'socket' was terminated.
*EFAULT*:: *ENOTSOCK*::
The provided 'socket' was not valid (NULL). The provided 'socket' was invalid.
*EINTR*:: *EINTR*::
The operation was interrupted by delivery of a signal. The operation was interrupted by delivery of a signal.

View File

@ -309,7 +309,7 @@ ERRORS
*EINVAL*:: *EINVAL*::
The requested socket 'type' is invalid. The requested socket 'type' is invalid.
*EFAULT*:: *EFAULT*::
The provided 'context' was not valid (NULL). The provided 'context' is invalid.
*ETERM*:: *ETERM*::
The context specified was terminated. The context specified was terminated.

View File

@ -46,7 +46,7 @@ return `-1` and set 'errno' to one of the values defined below.
ERRORS ERRORS
------ ------
*EFAULT*:: *EFAULT*::
The provided 'context' was not valid (NULL). The provided 'context' was invalid.
*EINTR*:: *EINTR*::
Termination was interrupted by a signal. It can be restarted if needed. Termination was interrupted by a signal. It can be restarted if needed.

View File

@ -36,6 +36,7 @@
#endif #endif
zmq::ctx_t::ctx_t (uint32_t io_threads_) : zmq::ctx_t::ctx_t (uint32_t io_threads_) :
tag (0xbadcafe0),
terminating (false) terminating (false)
{ {
int rc; int rc;
@ -78,6 +79,11 @@ zmq::ctx_t::ctx_t (uint32_t io_threads_) :
zmq_assert (rc == 0); zmq_assert (rc == 0);
} }
bool zmq::ctx_t::check_tag ()
{
return tag == 0xbadcafe0;
}
zmq::ctx_t::~ctx_t () zmq::ctx_t::~ctx_t ()
{ {
// Check that there are no remaining sockets. // Check that there are no remaining sockets.
@ -99,6 +105,9 @@ zmq::ctx_t::~ctx_t ()
// needed as mailboxes themselves were deallocated with their // needed as mailboxes themselves were deallocated with their
// corresponding io_thread/socket objects. // corresponding io_thread/socket objects.
free (slots); free (slots);
// Remove the tag, so that the object is considered dead.
tag = 0xdeadbeef;
} }
int zmq::ctx_t::terminate () int zmq::ctx_t::terminate ()

View File

@ -60,6 +60,9 @@ namespace zmq
// of I/O thread pool to create. // of I/O thread pool to create.
ctx_t (uint32_t io_threads_); 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 // 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 // no more sockets open it'll cause all the infrastructure to be shut
// down. If there are open sockets still, the deallocation happens // down. If there are open sockets still, the deallocation happens
@ -98,6 +101,9 @@ namespace zmq
~ctx_t (); ~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 // Sockets belonging to this context. We need the list so that
// we can notify the sockets when zmq_term() is called. The sockets // we can notify the sockets when zmq_term() is called. The sockets
// will return ETERM then. // will return ETERM then.

View File

@ -61,6 +61,11 @@
#include "xpub.hpp" #include "xpub.hpp"
#include "xsub.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_, zmq::socket_base_t *zmq::socket_base_t::create (int type_, class ctx_t *parent_,
uint32_t tid_) 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_) : zmq::socket_base_t::socket_base_t (ctx_t *parent_, uint32_t tid_) :
own_t (parent_, tid_), own_t (parent_, tid_),
tag (0xbaddecaf),
ctx_terminated (false), ctx_terminated (false),
destroyed (false), destroyed (false),
last_tsc (0), last_tsc (0),
@ -126,6 +132,9 @@ zmq::socket_base_t::~socket_base_t ()
sessions_sync.lock (); sessions_sync.lock ();
zmq_assert (sessions.empty ()); zmq_assert (sessions.empty ());
sessions_sync.unlock (); sessions_sync.unlock ();
// Mark the socket as dead.
tag = 0xdeadbeef;
} }
zmq::mailbox_t *zmq::socket_base_t::get_mailbox () zmq::mailbox_t *zmq::socket_base_t::get_mailbox ()

View File

@ -50,6 +50,9 @@ namespace zmq
public: public:
// Returns false if object is not a socket.
bool check_tag ();
// Create a socket of a specified type. // Create a socket of a specified type.
static socket_base_t *create (int type_, class ctx_t *parent_, static socket_base_t *create (int type_, class ctx_t *parent_,
uint32_t tid_); uint32_t tid_);
@ -136,6 +139,9 @@ namespace zmq
private: private:
// Used to check whether the object is a socket.
uint32_t tag;
// If true, associated context was already terminated. // If true, associated context was already terminated.
bool ctx_terminated; bool ctx_terminated;

View File

@ -261,7 +261,7 @@ void *zmq_init (int io_threads_)
int zmq_term (void *ctx_) int zmq_term (void *ctx_)
{ {
if (!ctx_) { if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) {
errno = EFAULT; errno = EFAULT;
return -1; return -1;
} }
@ -287,7 +287,7 @@ int zmq_term (void *ctx_)
void *zmq_socket (void *ctx_, int type_) void *zmq_socket (void *ctx_, int type_)
{ {
if (!ctx_) { if (!ctx_ || !((zmq::ctx_t*) ctx_)->check_tag ()) {
errno = EFAULT; errno = EFAULT;
return NULL; return NULL;
} }
@ -296,8 +296,8 @@ void *zmq_socket (void *ctx_, int type_)
int zmq_close (void *s_) int zmq_close (void *s_)
{ {
if (!s_) { if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
errno = EFAULT; errno = ENOTSOCK;
return -1; return -1;
} }
((zmq::socket_base_t*) s_)->close (); ((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_, int zmq_setsockopt (void *s_, int option_, const void *optval_,
size_t optvallen_) size_t optvallen_)
{ {
if (!s_) { if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
errno = EFAULT; errno = ENOTSOCK;
return -1; return -1;
} }
return (((zmq::socket_base_t*) s_)->setsockopt (option_, optval_, 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_) int zmq_getsockopt (void *s_, int option_, void *optval_, size_t *optvallen_)
{ {
if (!s_) { if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
errno = EFAULT; errno = ENOTSOCK;
return -1; return -1;
} }
return (((zmq::socket_base_t*) s_)->getsockopt (option_, optval_, 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_) int zmq_bind (void *s_, const char *addr_)
{ {
if (!s_) { if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
errno = EFAULT; errno = ENOTSOCK;
return -1; return -1;
} }
return (((zmq::socket_base_t*) s_)->bind (addr_)); 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_) int zmq_connect (void *s_, const char *addr_)
{ {
if (!s_) { if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
errno = EFAULT; errno = ENOTSOCK;
return -1; return -1;
} }
return (((zmq::socket_base_t*) s_)->connect (addr_)); 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_) int zmq_sendmsg (void *s_, zmq_msg_t *msg_, int flags_)
{ {
if (!s_) { if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
errno = EFAULT; errno = ENOTSOCK;
return -1; return -1;
} }
int sz = (int) zmq_msg_size (msg_); 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_) int zmq_recvmsg (void *s_, zmq_msg_t *msg_, int flags_)
{ {
if (!s_) { if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
errno = EFAULT; errno = ENOTSOCK;
return -1; return -1;
} }
int rc = (((zmq::socket_base_t*) s_)->recv (msg_, flags_)); int rc = (((zmq::socket_base_t*) s_)->recv (msg_, flags_));