Problem : if socket is invalid for any reason, as_socket_base_t() will return NULL and 'as_socket_base_t (items_[i].socket)->is_thread_safe ()' will crash (#4004)

* Problem : if socket is invalid for any reason, as_socket_base_t() will return NULL and 'as_socket_base_t (items_[i].socket)->is_thread_safe ()' will crash

Solution: expand the code to test the returned value from as_socket_base_t() before calling is_thread_safe() and make zmq_poll() return -1 if as_socket_base_t() returned NULL.

NB: this occurred on the destruction of a SUB socket while running a zloop and without previously calling zloop_reader_set_tolerant and zloop_reader_end. When entering zmq_poll, the PUB socket was already destroyed but still registered in the poll items.

NB: making zmq_poll return -1 is OK as it is what happens anyway, and errno is properly set to ENOTSOCK by as_socket_base_t() when it returns NULL.

Co-authored-by: Stéphane Valès <stephane@vales.fr@users.noreply.github.com>
This commit is contained in:
Stéphane Valès 2020-08-07 10:13:52 +02:00 committed by GitHub
parent 5d77cd8118
commit 3da6fde592
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -855,9 +855,15 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
// if poller is present, use that if there is at least 1 thread-safe socket,
// otherwise fall back to the previous implementation as it's faster.
for (int i = 0; i != nitems_; i++) {
if (items_[i].socket
&& as_socket_base_t (items_[i].socket)->is_thread_safe ()) {
return zmq_poller_poll (items_, nitems_, timeout_);
if (items_[i].socket) {
zmq::socket_base_t *s = as_socket_base_t (items_[i].socket);
if (s) {
if (s->is_thread_safe ())
return zmq_poller_poll (items_, nitems_, timeout_);
} else {
//as_socket_base_t returned NULL : socket is invalid
return -1;
}
}
}
#endif // ZMQ_HAVE_POLLER