Example #1
0
static ssize_t
ngx_zeromq_send_part(void *zmq, ngx_event_t *wev, u_char *buf, size_t size,
    int flags)
{
    zmq_msg_t  zmq_msg;

    if (zmq_msg_init_size(&zmq_msg, size) == -1) {
        ngx_log_error(NGX_LOG_ALERT, wev->log, 0,
                      "zmq_msg_init_size(%uz) failed (%d: %s)",
                      size, ngx_errno, zmq_strerror(ngx_errno));
        goto failed_zmq;
    }

    ngx_memcpy(zmq_msg_data(&zmq_msg), buf, size);

    for (;;) {
        if (zmq_sendmsg(zmq, &zmq_msg, ZMQ_DONTWAIT|flags) == -1) {

            if (ngx_errno == NGX_EINTR) {
                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
                               "zmq_send: interrupted");
                wev->ready = 0;
                continue;
            }

            ngx_zeromq_log_error(wev->log, "zmq_sendmsg()");
            goto failed;
        }

        break;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, wev->log, 0,
                   "zmq_send: %uz eom:%d", size, flags != ZMQ_SNDMORE);

    if (zmq_msg_close(&zmq_msg) == -1) {
        ngx_zeromq_log_error(wev->log, "zmq_msg_close()");
        goto failed_zmq;
    }

    return size;

failed:

    if (zmq_msg_close(&zmq_msg) == -1) {
        ngx_zeromq_log_error(wev->log, "zmq_msg_close()");
    }

failed_zmq:

    wev->error = 1;
    return NGX_ERROR;
}
Example #2
0
static void
ngx_zeromq_process_exit(ngx_cycle_t *cycle)
{
    if (zmq_context != NULL && zmq_term(zmq_context) == -1) {
        ngx_zeromq_log_error(cycle->log, "zmq_term()");
    }
}
Example #3
0
static ssize_t
ngx_zeromq_send_part(void *zmq, ngx_event_t *wev, u_char *buf, size_t size,
    int flags)
{
    zmq_msg_t  zmq_msg;
    ssize_t    n;

    if (zmq_msg_init_size(&zmq_msg, size) == -1) {
        ngx_log_error(NGX_LOG_ALERT, wev->log, 0,
                      "zmq_msg_init_size(%uz) failed (%d: %s)",
                      size, ngx_errno, zmq_strerror(ngx_errno));
        return NGX_ERROR;
    }

    ngx_memcpy(zmq_msg_data(&zmq_msg), buf, size);

    n = ngx_zeromq_sendmsg(zmq, wev, &zmq_msg, flags);

    if (zmq_msg_close(&zmq_msg) == -1) {
        ngx_zeromq_log_error(wev->log, "zmq_msg_close()");
        return NGX_ERROR;
    }

    return n;
}
Example #4
0
static ssize_t
ngx_zeromq_recvmsg(void *zmq, ngx_event_t *ev, zmq_msg_t *msg)
{
    int  more;

    for (;;) {
        if (zmq_msg_recv(msg, zmq, ZMQ_DONTWAIT) == -1) {

            if (ngx_errno == NGX_EAGAIN) {
                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                               "zmq_recv: not ready");
                ev->ready = 0;
                return NGX_AGAIN;
            }

            if (ngx_errno == NGX_EINTR) {
                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                               "zmq_recv: interrupted");
                ev->ready = 0;
                continue;
            }

            ngx_zeromq_log_error(ev->log, "zmq_msg_recv()");

            ev->error = 1;
            return NGX_ERROR;
        }

        break;
    }

    more = zmq_msg_get(msg, ZMQ_MORE);

    if (more == -1) {
        ngx_zeromq_log_error(ev->log, "zmq_msg_more()");

        ev->error = 1;
        return NGX_ERROR;
    }

    ev->eof = more ? 0 : 1;

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                   "zmq_recv: %uz eom:%d", zmq_msg_size(msg), ev->eof);

    return zmq_msg_size(msg);
}
Example #5
0
void
ngx_zeromq_close(ngx_connection_t *c)
{
    void  *zmq;

    if (c->fd == -1) {
        return;
    }

    zmq = c->data;

    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   "zmq_close: zmq:%p fd:%d #%d", zmq, c->fd, c->number);

    if (c->read->timer_set) {
        ngx_del_timer(c->read);
    }

    if (c->write->timer_set) {
        ngx_del_timer(c->write);
    }

    if (ngx_del_conn) {
        ngx_del_conn(c, NGX_CLOSE_EVENT);

    } else {
        if (c->read->active || c->read->disabled) {
            ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
        }

        if (c->write->active || c->write->disabled) {
            ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
        }
    }

    if (c->read->prev) {
        ngx_delete_posted_event(c->read);
    }

    if (c->write->prev) {
        ngx_delete_posted_event(c->write);
    }

    c->read->closed = 1;
    c->write->closed = 1;

    ngx_reusable_connection(c, 0);

    ngx_free_connection(c);

    c->fd = (ngx_socket_t) -1;

    if (zmq_close(zmq) == -1) {
        ngx_zeromq_log_error(ngx_cycle->log, "zmq_close()");
    }
}
Example #6
0
static void
ngx_zeromq_process_exit(ngx_cycle_t *cycle)
{
    if (ngx_zeromq_ctx) {
        if (zmq_ctx_destroy(ngx_zeromq_ctx) == -1) {
            ngx_zeromq_log_error(cycle->log, "zmq_ctx_destroy()");
        }

        ngx_zeromq_ctx = NULL;
    }
}
Example #7
0
static ngx_int_t
ngx_zeromq_process_init(ngx_cycle_t *cycle)
{
    ngx_zeromq_conf_t  *zcf;

    zcf = (ngx_zeromq_conf_t *) ngx_get_conf(cycle->conf_ctx,
                                             ngx_zeromq_module);

    if (ngx_zeromq_used) {
        ngx_zeromq_ctx = zmq_ctx_new();

        if (ngx_zeromq_ctx == NULL) {
            ngx_zeromq_log_error(cycle->log, "zmq_ctx_new()");
            return NGX_ERROR;
        }

        if (zmq_ctx_set(ngx_zeromq_ctx, ZMQ_IO_THREADS, zcf->threads) == -1) {
            ngx_zeromq_log_error(cycle->log, "zmq_ctx_set(ZMQ_IO_THREADS)");
        }
    }

    return NGX_OK;
}
Example #8
0
static ssize_t
ngx_zeromq_recv_part(void *zmq, ngx_event_t *rev, u_char *buf, size_t size)
{
    zmq_msg_t  zmq_msg;
    ssize_t    n;

    if (zmq_msg_init(&zmq_msg) == -1) {
        ngx_zeromq_log_error(rev->log, "zmq_msg_init()");
        return NGX_ERROR;
    }

    n = ngx_zeromq_recvmsg(zmq, rev, &zmq_msg);
    if (n < 0) {
        goto done;
    }

    if ((size_t) n > size) {
        ngx_log_error(NGX_LOG_ALERT, rev->log, 0,
                      "zmq_recv: ZeroMQ message part too big (%uz) to fit"
                      " into buffer (%uz)", n, size);

        n = NGX_ERROR;
        goto done;
    }

    ngx_memcpy(buf, zmq_msg_data(&zmq_msg), n);

done:

    if (zmq_msg_close(&zmq_msg) == -1) {
        ngx_zeromq_log_error(rev->log, "zmq_msg_close()");
        return NGX_ERROR;
    }

    return n;
}
Example #9
0
static ngx_int_t
ngx_zeromq_process_init(ngx_cycle_t *cycle)
{
    ngx_zeromq_conf_t  *zcf;

    zcf = (ngx_zeromq_conf_t *) ngx_get_conf(cycle->conf_ctx,
                                             ngx_zeromq_module);

    if (zmq_used) {
        zmq_context = zmq_init(zcf->threads);

        if (zmq_context == NULL) {
            ngx_zeromq_log_error(cycle->log, "zmq_init()");
            return NGX_ERROR;
        }
    }

    return NGX_OK;
}
Example #10
0
static ngx_int_t
ngx_zeromq_ready(void *zmq, ngx_event_t *ev, const char *what, uint32_t want)
{
    uint32_t  flags;
    size_t    fsize;

    fsize = sizeof(uint32_t);

    if (zmq_getsockopt(zmq, ZMQ_EVENTS, &flags, &fsize) == -1) {
        ngx_zeromq_log_error(ev->log, "zmq_getsockopt(ZMQ_EVENTS)");

        ev->error = 1;
        return NGX_ERROR;
    }

    if (!(flags & want)) {
        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, "%s: not ready", what);

        ev->ready = 0;
        return NGX_AGAIN;
    }

    return NGX_OK;
}
Example #11
0
static ssize_t
ngx_zeromq_recv_part(void *zmq, ngx_event_t *rev, u_char *buf, size_t size)
{
    zmq_msg_t  zmq_msg;
    int64_t    more;
    size_t     msize;

    if (zmq_msg_init(&zmq_msg) == -1) {
        ngx_zeromq_log_error(rev->log, "zmq_msg_init()");
        goto failed_zmq;
    }

    for (;;) {
        if (zmq_recvmsg(zmq, &zmq_msg, ZMQ_DONTWAIT) == -1) {

            if (ngx_errno == NGX_EINTR) {
                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
                               "zmq_recv: interrupted");
                rev->ready = 0;
                continue;
            }

            ngx_zeromq_log_error(rev->log, "zmq_recvmsg()");
            goto failed;
        }

        break;
    }

    if (zmq_msg_size(&zmq_msg) > size) {
        ngx_log_error(NGX_LOG_ALERT, rev->log, 0,
                      "zmq_recv: ZeroMQ message part too big (%uz) to fit"
                      " into buffer (%uz)", zmq_msg_size(&zmq_msg), size);
        goto failed;
    }

    msize = sizeof(int64_t);

    if (zmq_getsockopt(zmq, ZMQ_RCVMORE, &more, &msize) == -1) {
        ngx_zeromq_log_error(rev->log, "zmq_getsockopt(ZMQ_RCVMORE)");
        goto failed;
    }

    rev->eof = more ? 0 : 1;

    size = zmq_msg_size(&zmq_msg);

    ngx_memcpy(buf, zmq_msg_data(&zmq_msg), size);

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, rev->log, 0,
                   "zmq_recv: %uz eom:%d", size, rev->eof);

    if (zmq_msg_close(&zmq_msg) == -1) {
        ngx_zeromq_log_error(rev->log, "zmq_msg_close()");
        goto failed_zmq;
    }

    return size;

failed:

    if (zmq_msg_close(&zmq_msg) == -1) {
        ngx_zeromq_log_error(rev->log, "zmq_msg_close()");
    }

failed_zmq:

    rev->error = 1;
    return NGX_ERROR;
}
Example #12
0
ngx_int_t
ngx_zeromq_connect(ngx_peer_connection_t *pc)
{
    ngx_connection_t  *c;
    ngx_event_t       *rev, *wev;
    void              *zmq;
    int                fd, zero;
    size_t             fdsize;

    zmq = zmq_socket(zmq_context, ZMQ_REQ);
    if (zmq == NULL) {
        ngx_zeromq_log_error(pc->log, "zmq_socket(ZMQ_REQ)");
        return NGX_ERROR;
    }

    fdsize = sizeof(int);

    if (zmq_getsockopt(zmq, ZMQ_FD, &fd, &fdsize) == -1) {
        ngx_zeromq_log_error(pc->log, "zmq_getsockopt(ZMQ_FD)");
        goto failed_zmq;
    }

    zero = 0;

    if (zmq_setsockopt(zmq, ZMQ_LINGER, &zero, sizeof(int)) == -1) {
        ngx_zeromq_log_error(pc->log, "zmq_setsockopt(ZMQ_LINGER)");
        goto failed_zmq;
    }

    c = ngx_get_connection(fd, pc->log);
    if (c == NULL) {
        goto failed_zmq;
    }

    c->data = zmq;

    c->recv = ngx_zeromq_recv;
    c->send = ngx_zeromq_send;
    c->recv_chain = ngx_zeromq_recv_chain;
    c->send_chain = ngx_zeromq_send_chain;

    /* This won't fly with ZeroMQ */
    c->sendfile = 0;
    c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
    c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;

    c->log_error = pc->log_error;

    rev = c->read;
    wev = c->write;

    rev->log = pc->log;
    wev->log = pc->log;

    pc->connection = c;

    c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);

    if (pc->local) {
        ngx_log_error(NGX_LOG_WARN, pc->log, 0,
                      "zmq_connect: binding to local address is not supported");
    }

    if (zmq_connect(zmq, (const char *) pc->data) == -1) {
        ngx_zeromq_log_error(pc->log, "zmq_connect()");
        goto failed;
    }

    ngx_log_debug4(NGX_LOG_DEBUG_EVENT, pc->log, 0,
                   "zmq_connect: lazily connected to tcp://%V,"
                   " zmq:%p fd:%d #%d", pc->name, zmq, fd, c->number);

    if (ngx_add_conn) {
        /* rtsig */
        if (ngx_add_conn(c) == NGX_ERROR) {
            goto failed;
        }

    } else {
        if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
            /* kqueue, epoll */
            if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) {
                goto failed;
            }

        } else {
            /* select, poll, /dev/poll */
            if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) != NGX_OK) {
                goto failed;
            }
        }
    }

    /*
     * ZeroMQ assumes that new socket is read-ready (but it really isn't)
     * and it won't notify us about any new events if we don't fail to read
     * from it first. Sigh.
     */

    rev->ready = 1;
    wev->ready = 1;

    return NGX_OK;

failed:

    ngx_free_connection(c);

    c->fd = (ngx_socket_t) -1;

failed_zmq:

    if (zmq_close(zmq) == -1) {
        ngx_zeromq_log_error(pc->log, "zmq_close()");
    }

    return NGX_ERROR;
}
Example #13
0
void
ngx_zeromq_close(ngx_zeromq_connection_t *zc)
{
    ngx_connection_t  *c;

    c = &zc->connection;

    if (c->fd == -1) {
        return;
    }

    ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   "zmq_close: fd:%d #%d zc:%p zmq:%p",
                   c->fd, c->number, zc, zc->socket);

    if (c->read->timer_set) {
        ngx_del_timer(c->read);
    }

    if (c->write->timer_set) {
        ngx_del_timer(c->write);
    }

    if (ngx_del_conn) {
        ngx_del_conn(c, NGX_CLOSE_EVENT);

    } else {
        if (c->read->active || c->read->disabled) {
            ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
        }

        if (c->write->active || c->write->disabled) {
            ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
        }
    }

#if (nginx_version >= 1007005)
    if (c->read->posted) {
#else
    if (c->read->prev) {
#endif
        ngx_delete_posted_event(c->read);
    }

#if (nginx_version >= 1007005)
    if (c->write->posted) {
#else
    if (c->write->prev) {
#endif
        ngx_delete_posted_event(c->write);
    }

    c->read->closed = 1;
    c->write->closed = 1;

    ngx_reusable_connection(zc->connection_ptr, 0);

    ngx_free_connection(zc->connection_ptr);

    c->fd = (ngx_socket_t) -1;
    zc->connection_ptr->fd = (ngx_socket_t) -1;

    if (zmq_close(zc->socket) == -1) {
        ngx_zeromq_log_error(ngx_cycle->log, "zmq_close()");
    }

    zc->socket = NULL;
}


static void
ngx_zeromq_event_handler(ngx_event_t *ev)
{
    ngx_zeromq_connection_t  *zc;
    ngx_connection_t         *c;
    void                     *zmq;
    int                       events;
    size_t                    esize;

    /*
     * ZeroMQ notifies us about new events in edge-triggered fashion
     * by changing state of the notification socket to read-ready.
     *
     * Write-readiness doesn't indicate anything and can be ignored.
     */

    if (ev->write) {
        return;
    }

    zc = ev->data;
    zc = zc->send;

    esize = sizeof(int);

#if (NGX_DEBUG)
    if (zc->recv != zc->send) {
        zmq = zc->request_sent ? zc->socket : zc->recv->socket;

        if (zmq_getsockopt(zmq, ZMQ_EVENTS, &events, &esize) == -1) {
            ngx_zeromq_log_error(ev->log, "zmq_getsockopt(ZMQ_EVENTS)");
            ev->error = 1;
            return;
        }

        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                       "zmq_event: %s:%d (ignored)",
                       zc->request_sent ? "send" : "recv", events);
    }
#endif

    zmq = zc->request_sent ? zc->recv->socket : zc->socket;

    if (zmq_getsockopt(zmq, ZMQ_EVENTS, &events, &esize) == -1) {
        ngx_zeromq_log_error(ev->log, "zmq_getsockopt(ZMQ_EVENTS)");
        ev->error = 1;
        return;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                   "zmq_event: %s:%d",
                   zc->request_sent ? "recv" : "send", events);

    c = &zc->connection;

    if (zc->request_sent) {
        c->read->ready = events & ZMQ_POLLIN ? 1 : 0;

        if (c->read->ready) {
            zc->handler(c->read);
        }

    } else {
        c->write->ready = events & ZMQ_POLLOUT ? 1 : 0;

        if (c->write->ready) {
            zc->handler(c->write);
        }
    }
}


static ssize_t
ngx_zeromq_sendmsg(void *zmq, ngx_event_t *ev, zmq_msg_t *msg, int flags)
{
    size_t  size;

    size = zmq_msg_size(msg);

    for (;;) {
        if (zmq_msg_send(msg, zmq, ZMQ_DONTWAIT|flags) == -1) {

            if (ngx_errno == NGX_EAGAIN) {
                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                               "zmq_send: not ready");
                ev->ready = 0;
                return NGX_AGAIN;
            }

            if (ngx_errno == NGX_EINTR) {
                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                               "zmq_send: interrupted");
                ev->ready = 0;
                continue;
            }

            ngx_zeromq_log_error(ev->log, "zmq_msg_send()");

            ev->error = 1;
            return NGX_ERROR;
        }

        break;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                   "zmq_send: %uz eom:%d", size, flags != ZMQ_SNDMORE);

    return size;
}
Example #14
0
ngx_int_t
ngx_zeromq_connect(ngx_peer_connection_t *pc)
{
    ngx_zeromq_connection_t  *zc = pc->data;
    ngx_zeromq_endpoint_t    *zep;
    ngx_connection_t         *c;
    ngx_event_t              *rev, *wev;
    void                     *zmq;
    int                       fd, zero;
    size_t                    fdsize;
    ngx_uint_t                i;

    zep = zc->endpoint;

    zmq = zmq_socket(ngx_zeromq_ctx, zep->type->value);
    if (zmq == NULL) {
        ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
                      "zmq_socket(%V) failed (%d: %s)",
                      &zep->type->name, ngx_errno, zmq_strerror(ngx_errno));
        return NGX_ERROR;
    }

    fdsize = sizeof(int);

    if (zmq_getsockopt(zmq, ZMQ_FD, &fd, &fdsize) == -1) {
        ngx_zeromq_log_error(pc->log, "zmq_getsockopt(ZMQ_FD)");
        goto failed_zmq;
    }

    zero = 0;

    if (zmq_setsockopt(zmq, ZMQ_LINGER, &zero, sizeof(int)) == -1) {
        ngx_zeromq_log_error(pc->log, "zmq_setsockopt(ZMQ_LINGER)");
        goto failed_zmq;
    }

    c = ngx_get_connection(fd, pc->log);
    if (c == NULL) {
        goto failed_zmq;
    }

    c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);

    c->recv = ngx_zeromq_recv;
    c->send = NULL;
    c->recv_chain = ngx_zeromq_recv_chain;
    c->send_chain = ngx_zeromq_send_chain;

    /* This won't fly with ZeroMQ */
    c->sendfile = 0;
    c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
    c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;

    c->log_error = pc->log_error;

    rev = c->read;
    wev = c->write;

    rev->data = zc;
    wev->data = zc;

    rev->handler = ngx_zeromq_event_handler;
    wev->handler = ngx_zeromq_event_handler;

    rev->log = pc->log;
    wev->log = pc->log;

    pc->connection = &zc->connection;
    zc->connection_ptr = c;

    memcpy(&zc->connection, c, sizeof(ngx_connection_t));

    zc->socket = zmq;

    if (zep->type->can_send) {
        zc->send = zc;
    }

    if (zep->type->can_recv) {
        zc->recv = zc;
    }

    if (pc->local) {
        ngx_log_error(NGX_LOG_WARN, pc->log, 0,
                      "zmq_connect: binding to local address is not supported");
    }

    if (zep->bind) {
        if (zep->rand) {
            for (i = 0; ; i++) {
                ngx_zeromq_randomized_endpoint_regen(&zep->addr);

                if (zmq_bind(zmq, (const char *) zep->addr.data) == -1) {

                    if (ngx_errno == NGX_EADDRINUSE && i < 65535) {
                        continue;
                    }

                    ngx_zeromq_log_error(pc->log, "zmq_bind()");
                    goto failed;
                }

                break;
            }

        } else {
            if (zmq_bind(zmq, (const char *) zep->addr.data) == -1) {
                ngx_zeromq_log_error(pc->log, "zmq_bind()");
                goto failed;
            }
        }

    } else {
        if (zmq_connect(zmq, (const char *) zep->addr.data) == -1) {
            ngx_zeromq_log_error(pc->log, "zmq_connect()");
            goto failed;
        }
    }

    ngx_log_debug7(NGX_LOG_DEBUG_EVENT, pc->log, 0,
                   "zmq_connect: %s to %V (%V), fd:%d #%d zc:%p zmq:%p",
                   zep->bind ? "bound" : "lazily connected",
                   &zep->addr, &zep->type->name, fd, c->number, zc, zmq);

    if (ngx_add_conn) {
        /* rtsig */
        if (ngx_add_conn(c) == NGX_ERROR) {
            goto failed;
        }

    } else {
        if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
            /* kqueue, epoll */
            if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) {
                goto failed;
            }

        } else {
            /* select, poll, /dev/poll */
            if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) != NGX_OK) {
                goto failed;
            }
        }
    }

    /*
     * ZeroMQ assumes that new socket is read-ready (but it really isn't)
     * and it won't notify us about any new events if we don't fail to read
     * from it first. Sigh.
     */

    rev->ready = 1;
    wev->ready = zep->type->can_send;

    return NGX_OK;

failed:

    ngx_free_connection(c);

    c->fd = (ngx_socket_t) -1;

    pc->connection = NULL;
    zc->socket = NULL;

failed_zmq:

    if (zmq_close(zmq) == -1) {
        ngx_zeromq_log_error(pc->log, "zmq_close()");
    }

    return NGX_ERROR;
}