kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 4c39ac43fbbaf67a280d31372ddbe1f087429d11
parent dfea3cf483e69830d7cba4b1d76621020c8066a3
Author: Joris Vink <joris@coders.se>
Date:   Mon, 20 Apr 2015 15:17:42 +0200

Properly deal with accept() failing.

In cases where accept() failed Kore would not relinquish the
lock towards other worker processes.

This becomes evident when dealing with a high number of concurrent
connections to the point the fd table gets full. In this scenario
the worker with the full fd table will spin on attempt to accept
newer connections.

As a bonus, Kore now has allows exactly up to worker_max_connections
of connections per worker before no longer attempting to grab the
accept lock.

Diffstat:
src/bsd.c | 6+++++-
src/linux.c | 6+++++-
src/worker.c | 12++++++++++++
3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/bsd.c b/src/bsd.c @@ -153,7 +153,11 @@ kore_platform_event_wait(u_int64_t timer) while (worker_active_connections < worker_max_connections) { - kore_connection_accept(l, &c); + if (!kore_connection_accept(l, &c)) { + r = 1; + break; + } + if (c == NULL) break; diff --git a/src/linux.c b/src/linux.c @@ -130,7 +130,11 @@ kore_platform_event_wait(u_int64_t timer) while (worker_active_connections < worker_max_connections) { - kore_connection_accept(l, &c); + if (!kore_connection_accept(l, &c)) { + r = 1; + break; + } + if (c == NULL) break; diff --git a/src/worker.c b/src/worker.c @@ -20,6 +20,7 @@ #include <sys/time.h> #include <sys/resource.h> +#include <fcntl.h> #include <grp.h> #include <pwd.h> #include <signal.h> @@ -182,6 +183,7 @@ kore_worker_dispatch_signal(int sig) void kore_worker_entry(struct kore_worker *kw) { + size_t fd; struct rlimit rl; char buf[16]; struct connection *c, *cnext; @@ -197,6 +199,16 @@ kore_worker_entry(struct kore_worker *kw) fatal("cannot chdir(): %s", errno_s); } + if (getrlimit(RLIMIT_NOFILE, &rl) == -1) { + kore_log(LOG_WARNING, "getrlimit(RLIMIT_NOFILE): %s", errno_s); + } else { + for (fd = 0; fd < rl.rlim_cur; fd++) { + if (fcntl(fd, F_GETFD, NULL) != -1) { + worker_rlimit_nofiles++; + } + } + } + rl.rlim_cur = worker_rlimit_nofiles; rl.rlim_max = worker_rlimit_nofiles; if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {