Commit caf095a0 authored by Marek Vavrusa's avatar Marek Vavrusa

Implemented partial countermeasure against exhausting file descriptors.

parent 271d61b4
......@@ -28,6 +28,7 @@
#include "common/sockaddr.h"
#include "common/skip-list.h"
#include "common/fdset.h"
#include "common/WELL1024a.h"
#include "knot/common.h"
#include "knot/server/tcp-handler.h"
#include "knot/server/xfr-handler.h"
......@@ -47,6 +48,14 @@ typedef struct tcp_worker_t {
/*
* Forward decls.
*/
#define TCP_THROTTLE_LO 10 /*!< Minimum recovery time on errors. */
#define TCP_THROTTLE_HI 50 /*!< Maximum recovery time on errors. */
/*! \brief Calculate TCP throttle time (random). */
static inline int tcp_throttle() {
//(TCP_THROTTLE_LO + (int)(tls_rand() * TCP_THROTTLE_HI));
return (rand() % TCP_THROTTLE_HI) + TCP_THROTTLE_LO;
}
/*! \brief Wrapper for TCP send. */
static int xfr_send_cb(int session, sockaddr_t *addr, uint8_t *msg, size_t msglen)
......@@ -228,9 +237,21 @@ static int tcp_accept(int fd)
/* Evaluate connection. */
if (incoming < 0) {
if (errno != EINTR) {
int en = errno;
if (en != EINTR) {
log_server_error("Cannot accept connection "
"(%d).\n", errno);
if (en == EMFILE || en == ENFILE ||
en == ENOBUFS || en == ENOMEM) {
int throttle = tcp_throttle();
log_server_error("Throttling TCP connection pool"
" for %d seconds because of "
"too many open descriptors "
"or lack of memory.\n",
throttle);
sleep(throttle);
}
}
} else {
dbg_net("tcp: accepted connection fd=%d\n", incoming);
......
......@@ -427,29 +427,37 @@ static int zones_refresh_ev(event_t *e)
int sock = socket_create(master->family, SOCK_DGRAM);
/* Send query. */
ret = -1;
ret = KNOTD_ERROR;
if (sock > -1) {
ret = sendto(sock, qbuf, buflen, 0,
master->ptr, master->len);
int sent = sendto(sock, qbuf, buflen, 0,
master->ptr, master->len);
/* Store ID of the awaited response. */
if (sent == buflen) {
ret = KNOTD_EOK;
} else {
socket_close(sock);
sock = -1;
}
}
/* Store ID of the awaited response. */
if (ret == buflen) {
/* Check result. */
if (ret == KNOTD_EOK) {
zd->xfr_in.next_id = knot_wire_get_id(qbuf);
dbg_zones("zones: expecting SOA response "
"ID=%d for '%s'\n",
zd->xfr_in.next_id, zd->conf->name);
/* Watch socket. */
knot_ns_xfr_t req;
memset(&req, 0, sizeof(req));
req.session = sock;
req.type = XFR_TYPE_SOA;
req.zone = zone;
memcpy(&req.addr, master, sizeof(sockaddr_t));
sockaddr_update(&req.addr);
xfr_request(zd->server->xfr_h, &req);
}
/* Watch socket. */
knot_ns_xfr_t req;
memset(&req, 0, sizeof(req));
req.session = sock;
req.type = XFR_TYPE_SOA;
req.zone = zone;
memcpy(&req.addr, master, sizeof(sockaddr_t));
sockaddr_update(&req.addr);
xfr_request(zd->server->xfr_h, &req);
} else {
ret = KNOTD_ERROR;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment