From 773a06fc23526934e386875744ddbbb2413c2051 Mon Sep 17 00:00:00 2001 From: Brian Silverman Date: Wed, 22 Jul 2015 11:18:48 -0700 Subject: [PATCH] Fix memory leak when creating a socket fails. Previously, AddressSanitizer flagged leaks when running tests/test_many_sockets.cpp. --- src/signaler.cpp | 39 ++++++++++++++++++++++++--------------- src/socket_base.cpp | 5 ++++- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/signaler.cpp b/src/signaler.cpp index e6fa9833..52f08bed 100644 --- a/src/signaler.cpp +++ b/src/signaler.cpp @@ -133,28 +133,37 @@ zmq::signaler_t::signaler_t () #endif } +// This might get run after some part of construction failed, leaving one or +// both of r and w retired_fd. zmq::signaler_t::~signaler_t () { #if defined ZMQ_HAVE_EVENTFD + if (r == retired_fd) return; int rc = close_wait_ms (r); errno_assert (rc == 0); #elif defined ZMQ_HAVE_WINDOWS - const struct linger so_linger = { 1, 0 }; - int rc = setsockopt (w, SOL_SOCKET, SO_LINGER, - (const char *) &so_linger, sizeof so_linger); - // Only check shutdown if WSASTARTUP was previously done - if (rc == 0 || WSAGetLastError () != WSANOTINITIALISED) { - wsa_assert (rc != SOCKET_ERROR); - rc = closesocket (w); - wsa_assert (rc != SOCKET_ERROR); - rc = closesocket (r); - wsa_assert (rc != SOCKET_ERROR); - } + if (w != retired_fd) { + const struct linger so_linger = { 1, 0 }; + int rc = setsockopt (w, SOL_SOCKET, SO_LINGER, + (const char *) &so_linger, sizeof so_linger); + // Only check shutdown if WSASTARTUP was previously done + if (rc == 0 || WSAGetLastError () != WSANOTINITIALISED) { + wsa_assert (rc != SOCKET_ERROR); + rc = closesocket (w); + wsa_assert (rc != SOCKET_ERROR); + if (r == retired_fd) return; + rc = closesocket (r); + wsa_assert (rc != SOCKET_ERROR); + } #else - int rc = close_wait_ms (w); - errno_assert (rc == 0); - rc = close_wait_ms (r); - errno_assert (rc == 0); + if (w != retired_fd) { + int rc = close_wait_ms (w); + errno_assert (rc == 0); + } + if (r != retired_fd) { + rc = close_wait_ms (r); + errno_assert (rc == 0); + } #endif } diff --git a/src/socket_base.cpp b/src/socket_base.cpp index 79044b1a..5606c9b7 100644 --- a/src/socket_base.cpp +++ b/src/socket_base.cpp @@ -154,8 +154,11 @@ zmq::socket_base_t *zmq::socket_base_t::create (int type_, class ctx_t *parent_, mailbox_t *mailbox = dynamic_cast (s->mailbox); - if (mailbox != NULL && mailbox->get_fd () == retired_fd) + if (mailbox != NULL && mailbox->get_fd () == retired_fd) { + s->destroyed = true; + delete s; return NULL; + } return s; }