#include <sys/socket.h>
#include <sys/types.h>
+#undef ISC_NETMGR_TRACE
+
#if defined(SO_REUSEPORT_LB) || (defined(SO_REUSEPORT) && defined(__linux__))
#define HAVE_SO_REUSEPORT_LB 1
#endif
* \li 'listener' is a pointer to a valid network manager listener socket.
*/
-#ifdef NETMGR_TRACE
+#ifdef ISC_NETMGR_TRACE
#define isc_nmhandle_attach(handle, dest) \
isc__nmhandle_attach(handle, dest, __FILE__, __LINE__, __func__)
#define isc_nmhandle_detach(handlep) \
}
sock = isc_mem_get(worker->mctx, sizeof(*sock));
- isc__nmsocket_init(sock, worker, isc_nm_httpsocket, local);
+ isc__nmsocket_init(sock, worker, isc_nm_httpsocket, local, NULL);
sock->connect_timeout = timeout;
sock->connect_cb = cb;
worker = session->handle->sock->worker;
socket = isc_mem_get(worker->mctx, sizeof(isc_nmsocket_t));
isc__nmsocket_init(socket, worker, isc_nm_httpsocket,
- (isc_sockaddr_t *)&session->handle->sock->iface);
+ (isc_sockaddr_t *)&session->handle->sock->iface,
+ NULL);
socket->peer = session->handle->sock->peer;
socket->h2 = (isc_nmsocket_h2_t){
.psock = socket,
REQUIRE(isc_tid() == 0);
sock = isc_mem_get(worker->mctx, sizeof(*sock));
- isc__nmsocket_init(sock, worker, isc_nm_httplistener, iface);
+ isc__nmsocket_init(sock, worker, isc_nm_httplistener, iface, NULL);
atomic_init(&sock->h2.max_concurrent_streams,
NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS);
#define NM_MAXSEG (1280 - 20 - 40)
/*
- * Define NETMGR_TRACE to activate tracing of handles and sockets.
+ * Define ISC_NETMGR_TRACE to activate tracing of handles and sockets.
* This will impair performance but enables us to quickly determine,
* if netmgr resources haven't been cleaned up on shutdown, which ones
* are still in use.
*/
-#ifdef NETMGR_TRACE
+#if ISC_NETMGR_TRACE
#define TRACE_SIZE 8
-void
-isc__nm_dump_active(isc_nm_t *nm);
-
#if defined(__linux__)
#include <syscall.h>
#define gettid() (uint32_t) syscall(SYS_gettid)
#define gettid() (uint32_t) pthread_self()
#endif
-#ifdef NETMGR_TRACE_VERBOSE
#define NETMGR_TRACE_LOG(format, ...) \
fprintf(stderr, "%" PRIu32 ":%d:%s:%u:%s:" format, gettid(), \
isc_tid(), file, line, func, __VA_ARGS__)
-#else
-#define NETMGR_TRACE_LOG(format, ...) \
- (void)file; \
- (void)line; \
- (void)func;
-#endif
#define FLARG_PASS , file, line, func
#define FLARG \
isc___nm_uvreq_get(req, sock, __FILE__, __LINE__, __func__)
#define isc__nm_uvreq_put(req, sock) \
isc___nm_uvreq_put(req, sock, __FILE__, __LINE__, __func__)
-#define isc__nmsocket_init(sock, mgr, type, iface) \
- isc___nmsocket_init(sock, mgr, type, iface, __FILE__, __LINE__, \
- __func__)
+#define isc__nmsocket_init(sock, mgr, type, iface, parent) \
+ isc___nmsocket_init(sock, mgr, type, iface, parent, __FILE__, \
+ __LINE__, __func__)
#define isc__nmsocket_put(sockp) \
isc___nmsocket_put(sockp, __FILE__, __LINE__, __func__)
#define isc__nmsocket_attach(sock, target) \
#define FLARG_IEVENT_PASS(ievent)
#define isc__nm_uvreq_get(req, sock) isc___nm_uvreq_get(req, sock)
#define isc__nm_uvreq_put(req, sock) isc___nm_uvreq_put(req, sock)
-#define isc__nmsocket_init(sock, mgr, type, iface) \
- isc___nmsocket_init(sock, mgr, type, iface)
+#define isc__nmsocket_init(sock, mgr, type, iface, parent) \
+ isc___nmsocket_init(sock, mgr, type, iface, parent)
#define isc__nmsocket_put(sockp) isc___nmsocket_put(sockp)
#define isc__nmsocket_attach(sock, target) isc___nmsocket_attach(sock, target)
#define isc__nmsocket_detach(socketp) isc___nmsocket_detach(socketp)
char *recvbuf;
char *sendbuf;
bool recvbuf_inuse;
+
+ ISC_LIST(isc_nmsocket_t) active_sockets;
+
} isc__networker_t;
ISC_REFCOUNT_DECL(isc__networker);
+void
+isc__nm_dump_active(isc__networker_t *worker);
+
/*
* A general handle for a connection bound to a networker. For UDP
* connections we have peer address here, so both TCP and UDP can be
isc_sockaddr_t local;
isc_nm_opaquecb_t doreset; /* reset extra callback, external */
isc_nm_opaquecb_t dofree; /* free extra callback, external */
-#ifdef NETMGR_TRACE
+#if ISC_NETMGR_TRACE
void *backtrace[TRACE_SIZE];
int backtrace_size;
- LINK(isc_nmhandle_t) active_link;
#endif
+ LINK(isc_nmhandle_t) active_link;
void *opaque;
};
atomic_int_fast32_t send_udp_buffer_size;
atomic_int_fast32_t recv_tcp_buffer_size;
atomic_int_fast32_t send_tcp_buffer_size;
-
-#ifdef NETMGR_TRACE
- ISC_LIST(isc_nmsocket_t) active_sockets;
-#endif
};
/*%
bool barriers_initialised;
bool manual_read_timer;
-#ifdef NETMGR_TRACE
+#if ISC_NETMGR_TRACE
void *backtrace[TRACE_SIZE];
int backtrace_size;
+#endif
LINK(isc_nmsocket_t) active_link;
ISC_LIST(isc_nmhandle_t) active_handles;
- isc_mutex_t tracelock;
-#endif
};
void
*/
isc_nmhandle_t *
-isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
- isc_sockaddr_t *local FLARG);
+isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t const *peer,
+ isc_sockaddr_t const *local FLARG);
/*%<
* Get a handle for the socket 'sock', allocating a new one
* if there isn't one available in 'sock->inactivehandles'.
void
isc___nmsocket_init(isc_nmsocket_t *sock, isc__networker_t *worker,
- isc_nmsocket_type type, isc_sockaddr_t *iface FLARG);
+ isc_nmsocket_type type, isc_sockaddr_t *iface,
+ isc_nmsocket_t *parent FLARG);
/*%<
* Initialize socket 'sock', attach it to 'mgr', and set it to type 'type'
* and its interface to 'iface'.
netmgr->load_balance_sockets = false;
#endif
-#ifdef NETMGR_TRACE
- ISC_LIST_INIT(netmgr->active_sockets);
-#endif
-
/*
* Default TCP timeout values.
* May be updated by isc_nm_tcptimeouts().
ISC_NETMGR_RECVBUF_SIZE),
.sendbuf = isc_mem_get(loop->mctx,
ISC_NETMGR_SENDBUF_SIZE),
+ .active_sockets = ISC_LIST_INITIALIZER,
};
isc_nm_attach(netmgr, &worker->netmgr);
* Free all resources inside a socket (including its children if any).
*/
static void
-nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) {
- isc_nmhandle_t *handle = NULL;
- isc__nm_uvreq_t *uvreq = NULL;
-
+nmsocket_cleanup(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(!isc__nmsocket_active(sock));
- NETMGR_TRACE_LOG("nmsocket_cleanup():%p->references = %" PRIuFAST32
- "\n",
- sock, isc_refcount_current(&sock->references));
+ isc_nmhandle_t *handle = NULL;
+ isc__nm_uvreq_t *uvreq = NULL;
+ isc__networker_t *worker = sock->worker;
isc_refcount_destroy(&sock->references);
*/
for (size_t i = 0; i < sock->nchildren; i++) {
REQUIRE(!atomic_load(&sock->children[i].destroying));
- if (isc_refcount_decrement(
- &sock->children[i].references))
- {
- nmsocket_cleanup(&sock->children[i],
- false FLARG_PASS);
- }
+ isc_refcount_decrementz(&sock->children[i].references);
+ nmsocket_cleanup(&sock->children[i]);
}
/*
sock->magic = 0;
-#ifdef NETMGR_TRACE
- LOCK(&sock->worker->netmgr->lock);
- ISC_LIST_UNLINK(sock->worker->netmgr->active_sockets, sock,
- active_link);
- UNLOCK(&sock->worker->netmgr->lock);
- isc_mutex_destroy(&sock->tracelock);
-#endif
-
isc_mutex_destroy(&sock->lock);
- if (dofree) {
- isc__networker_t *worker = sock->worker;
+ /* Don't free child socket */
+ if (sock->parent == NULL) {
+ REQUIRE(sock->tid == isc_tid());
+
+ ISC_LIST_UNLINK(worker->active_sockets, sock, active_link);
+
isc_mem_put(worker->mctx, sock, sizeof(*sock));
- isc__networker_detach(&worker);
- } else {
- isc__networker_detach(&sock->worker);
}
+
+ isc__networker_detach(&worker);
}
static void
if (destroy) {
atomic_store(&sock->destroying, true);
- nmsocket_cleanup(sock, true FLARG_PASS);
+ if (sock->tid == isc_tid()) {
+ nmsocket_cleanup(sock);
+ } else {
+ isc_async_run(sock->worker->loop,
+ (isc_job_cb)nmsocket_cleanup, sock);
+ }
}
}
void
isc___nmsocket_init(isc_nmsocket_t *sock, isc__networker_t *worker,
- isc_nmsocket_type type, isc_sockaddr_t *iface FLARG) {
+ isc_nmsocket_type type, isc_sockaddr_t *iface,
+ isc_nmsocket_t *parent FLARG) {
uint16_t family;
REQUIRE(sock != NULL);
.inactivereqs = isc_astack_new(worker->mctx,
ISC_NM_REQS_STACK_SIZE),
.result = ISC_R_UNSET,
+ .active_handles = ISC_LIST_INITIALIZER,
+ .active_link = ISC_LINK_INITIALIZER,
};
isc_mutex_init(&sock->lock);
family = AF_UNSPEC;
}
-#if NETMGR_TRACE
+ if (parent) {
+ sock->parent = parent;
+ } else {
+ ISC_LIST_APPEND(worker->active_sockets, sock, active_link);
+ }
+
+#if ISC_NETMGR_TRACE
sock->backtrace_size = isc_backtrace(sock->backtrace, TRACE_SIZE);
- ISC_LINK_INIT(sock, active_link);
- ISC_LIST_INIT(sock->active_handles);
- LOCK(&worker->netmgr->lock);
- ISC_LIST_APPEND(worker->netmgr->active_sockets, sock, active_link);
- UNLOCK(&worker->netmgr->lock);
- isc_mutex_init(&sock->tracelock);
#endif
isc__networker_attach(worker, &sock->worker);
isc_nmhandle_t *handle = isc_mem_get(sock->worker->mctx,
sizeof(isc_nmhandle_t));
- *handle = (isc_nmhandle_t){ .magic = NMHANDLE_MAGIC };
-#ifdef NETMGR_TRACE
- ISC_LINK_INIT(handle, active_link);
-#endif
+ *handle = (isc_nmhandle_t){
+ .magic = NMHANDLE_MAGIC,
+ .active_link = ISC_LINK_INITIALIZER,
+ };
isc_refcount_init(&handle->references, 1);
return (handle);
}
isc_nmhandle_t *
-isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
- isc_sockaddr_t *local FLARG) {
+isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t const *peer,
+ isc_sockaddr_t const *local FLARG) {
isc_nmhandle_t *handle = NULL;
REQUIRE(VALID_NMSOCK(sock));
} else {
isc_refcount_init(&handle->references, 1);
INSIST(VALID_NMHANDLE(handle));
+ ISC_LINK_INIT(handle, active_link);
}
NETMGR_TRACE_LOG(
isc___nmsocket_attach(sock, &handle->sock FLARG_PASS);
-#if NETMGR_TRACE
+#if ISC_NETMGR_TRACE
handle->backtrace_size = isc_backtrace(handle->backtrace, TRACE_SIZE);
#endif
(void)atomic_fetch_add(&sock->ah, 1);
-#ifdef NETMGR_TRACE
- LOCK(&sock->tracelock);
ISC_LIST_APPEND(sock->active_handles, handle, active_link);
- UNLOCK(&sock->tracelock);
-#endif
switch (sock->type) {
case isc_nm_udpsocket:
* destruction. We have to do this now, because at this point the
* socket is either unused or still attached to event->sock.
*/
-#ifdef NETMGR_TRACE
ISC_LIST_UNLINK(sock->active_handles, handle, active_link);
-#endif
ah = atomic_fetch_sub(&sock->ah, 1);
INSIST(ah > 0);
void
isc__nmhandle_set_manual_timer(isc_nmhandle_t *handle, const bool manual) {
- isc_nmsocket_t *sock;
-
REQUIRE(VALID_NMHANDLE(handle));
- sock = handle->sock;
- REQUIRE(VALID_NMSOCK(sock));
+ REQUIRE(VALID_NMSOCK(handle->sock));
+
+ isc_nmsocket_t *sock = handle->sock;
switch (sock->type) {
case isc_nm_tcpsocket:
isc__nmhandle_get_selected_alpn(isc_nmhandle_t *handle,
const unsigned char **alpn,
unsigned int *alpnlen) {
- isc_nmsocket_t *sock;
-
REQUIRE(VALID_NMHANDLE(handle));
- sock = handle->sock;
- REQUIRE(VALID_NMSOCK(sock));
+ REQUIRE(VALID_NMSOCK(handle->sock));
+
+ isc_nmsocket_t *sock = handle->sock;
switch (sock->type) {
case isc_nm_tlssocket:
isc_result_t
isc_nmhandle_set_tcp_nodelay(isc_nmhandle_t *handle, const bool value) {
- isc_result_t result = ISC_R_FAILURE;
- isc_nmsocket_t *sock;
-
REQUIRE(VALID_NMHANDLE(handle));
- sock = handle->sock;
- REQUIRE(VALID_NMSOCK(sock));
+ REQUIRE(VALID_NMSOCK(handle->sock));
+
+ isc_result_t result = ISC_R_FAILURE;
+ isc_nmsocket_t *sock = handle->sock;
switch (sock->type) {
case isc_nm_tcpsocket: {
return (result);
}
-#ifdef NETMGR_TRACE
+#if ISC_NETMGR_TRACE
/*
* Dump all active sockets in netmgr. We output to stderr
* as the logger might be already shut down.
nmsocket_dump(isc_nmsocket_t *sock) {
isc_nmhandle_t *handle = NULL;
- LOCK(&sock->tracelock);
fprintf(stderr, "\n=================\n");
fprintf(stderr, "Active %s socket %p, type %s, refs %" PRIuFAST32 "\n",
atomic_load(&sock->client) ? "client" : "server", sock,
}
fprintf(stderr, "\n");
- UNLOCK(&sock->tracelock);
}
void
-isc__nm_dump_active(isc_nm_t *nm) {
+isc__nm_dump_active(isc__networker_t *worker) {
isc_nmsocket_t *sock = NULL;
+ bool first = true;
- REQUIRE(VALID_NM(nm));
-
- LOCK(&nm->lock);
- for (sock = ISC_LIST_HEAD(nm->active_sockets); sock != NULL;
+ for (sock = ISC_LIST_HEAD(worker->active_sockets); sock != NULL;
sock = ISC_LIST_NEXT(sock, active_link))
{
- static bool first = true;
if (first) {
fprintf(stderr, "Outstanding sockets\n");
first = false;
}
nmsocket_dump(sock);
}
- UNLOCK(&nm->lock);
}
#endif
type == isc_nm_streamdnslistener);
sock = isc_mem_get(worker->mctx, sizeof(*sock));
- isc__nmsocket_init(sock, worker, type, addr);
+ isc__nmsocket_init(sock, worker, type, addr, NULL);
sock->result = ISC_R_UNSET;
if (type == isc_nm_streamdnssocket) {
uint32_t initial = 0;
}
sock = isc_mem_get(worker->mctx, sizeof(*sock));
- isc__nmsocket_init(sock, worker, isc_nm_tcpsocket, local);
+ isc__nmsocket_init(sock, worker, isc_nm_tcpsocket, local, NULL);
sock->connect_timeout = timeout;
sock->fd = fd;
isc_nmsocket_t *csock = &sock->children[tid];
isc__networker_t *worker = &mgr->workers[tid];
- isc__nmsocket_init(csock, worker, isc_nm_tcpsocket, iface);
- csock->parent = sock;
+ isc__nmsocket_init(csock, worker, isc_nm_tcpsocket, iface, sock);
csock->accept_cb = sock->accept_cb;
csock->accept_cbarg = sock->accept_cbarg;
csock->backlog = sock->backlog;
REQUIRE(workers <= mgr->nloops);
sock = isc_mem_get(worker->mctx, sizeof(*sock));
- isc__nmsocket_init(sock, worker, isc_nm_tcplistener, iface);
+ isc__nmsocket_init(sock, worker, isc_nm_tcplistener, iface, NULL);
atomic_init(&sock->rchildren, 0);
sock->nchildren = (workers == ISC_NM_LISTEN_ALL) ? (uint32_t)mgr->nloops
csock = isc_mem_get(ssock->worker->mctx, sizeof(isc_nmsocket_t));
isc__nmsocket_init(csock, ssock->worker, isc_nm_tcpsocket,
- &ssock->iface);
+ &ssock->iface, NULL);
isc__nmsocket_attach(ssock, &csock->server);
csock->recv_cb = ssock->recv_cb;
csock->recv_cbarg = ssock->recv_cbarg;
*/
tlssock = isc_mem_get(handle->sock->worker->mctx, sizeof(*tlssock));
isc__nmsocket_init(tlssock, handle->sock->worker, isc_nm_tlssocket,
- &handle->sock->iface);
+ &handle->sock->iface, NULL);
/* We need to initialize SSL now to reference SSL_CTX properly */
tlsctx = tls_get_listener_tlsctx(tlslistensock, isc_tid());
tlssock = isc_mem_get(worker->mctx, sizeof(*tlssock));
- isc__nmsocket_init(tlssock, worker, isc_nm_tlslistener, iface);
+ isc__nmsocket_init(tlssock, worker, isc_nm_tlslistener, iface, NULL);
tlssock->accept_cb = accept_cb;
tlssock->accept_cbarg = accept_cbarg;
tls_init_listener_tlsctx(tlssock, sslctx);
}
nsock = isc_mem_get(worker->mctx, sizeof(*nsock));
- isc__nmsocket_init(nsock, worker, isc_nm_tlssocket, local);
+ isc__nmsocket_init(nsock, worker, isc_nm_tlssocket, local, NULL);
nsock->connect_cb = cb;
nsock->connect_cbarg = cbarg;
nsock->connect_timeout = timeout;
csock = &sock->children[tid];
- isc__nmsocket_init(csock, worker, isc_nm_udpsocket, iface);
- csock->parent = sock;
+ isc__nmsocket_init(csock, worker, isc_nm_udpsocket, iface, sock);
csock->recv_cb = sock->recv_cb;
csock->recv_cbarg = sock->recv_cbarg;
REQUIRE(workers <= mgr->nloops);
sock = isc_mem_get(worker->mctx, sizeof(isc_nmsocket_t));
- isc__nmsocket_init(sock, worker, isc_nm_udplistener, iface);
+ isc__nmsocket_init(sock, worker, isc_nm_udplistener, iface, NULL);
atomic_init(&sock->rchildren, 0);
sock->nchildren = (workers == ISC_NM_LISTEN_ALL) ? (uint32_t)mgr->nloops
}
sock = isc_mem_get(worker->mctx, sizeof(*sock));
- isc__nmsocket_init(sock, worker, isc_nm_udpsocket, NULL);
+ isc__nmsocket_init(sock, worker, isc_nm_udpsocket, NULL, NULL);
sock->connect_cb = cb;
sock->connect_cbarg = cbarg;
/* Initialize the new socket */
/* FIXME: Use per-worker mempool for new sockets */
sock = isc_mem_get(worker->mctx, sizeof(isc_nmsocket_t));
- isc__nmsocket_init(sock, worker, isc_nm_udpsocket, local);
+ isc__nmsocket_init(sock, worker, isc_nm_udpsocket, local, NULL);
sock->connect_cb = cb;
sock->connect_cbarg = cbarg;