summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Benoit <benno@cvs.openbsd.org>2013-10-20 09:36:30 +0000
committerSebastian Benoit <benno@cvs.openbsd.org>2013-10-20 09:36:30 +0000
commit406f5c093970c5b2d705bfe070f10d4625e0419d (patch)
tree300be5f9b9ba3050ca114960e3707f0f40933019
parentdb82081c484f61f9881c0ee2c390485ecd7dcd64 (diff)
reserve file descriptors for incoming connections so we
will be able to actually run the cgi for them later on. mirrored on relayd. ok florian@ blambert@
-rw-r--r--usr.sbin/slowcgi/slowcgi.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/usr.sbin/slowcgi/slowcgi.c b/usr.sbin/slowcgi/slowcgi.c
index f3c3f410c77..96f925cf2dc 100644
--- a/usr.sbin/slowcgi/slowcgi.c
+++ b/usr.sbin/slowcgi/slowcgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: slowcgi.c,v 1.18 2013/10/19 14:18:35 florian Exp $ */
+/* $OpenBSD: slowcgi.c,v 1.19 2013/10/20 09:36:29 benno Exp $ */
/*
* Copyright (c) 2013 David Gwynne <dlg@openbsd.org>
* Copyright (c) 2013 Florian Obser <florian@openbsd.org>
@@ -68,6 +68,9 @@
#define FCGI_OVERLOADED 2
#define FCGI_UNKNOWN_ROLE 3
+#define FD_RESERVE 5
+#define FD_NEEDED 6
+volatile int cgi_inflight = 0;
struct listener {
struct event ev, pause;
@@ -128,6 +131,7 @@ struct request {
int stderr_fd_closed;
uint8_t script_flags;
uint8_t request_started;
+ int inflight_fds_accounted;
};
struct requests {
@@ -157,6 +161,8 @@ struct fcgi_end_request_body {
__dead void usage(void);
void slowcgi_listen(char *, gid_t);
void slowcgi_paused(int, short, void *);
+int accept_reserve(int, struct sockaddr *, socklen_t *, int,
+ volatile int *);
void slowcgi_accept(int, short, void *);
void slowcgi_request(int, short, void *);
void slowcgi_response(int, short, void *);
@@ -366,6 +372,25 @@ slowcgi_paused(int fd, short events, void *arg)
event_add(&l->ev, NULL);
}
+int
+accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+ int reserve, volatile int *counter)
+{
+ int ret;
+ if (getdtablecount() + reserve +
+ (*counter * FD_NEEDED) >= getdtablesize()) {
+ ldebug("inflight fds exceded");
+ errno = EMFILE;
+ return -1;
+ }
+
+ if ((ret = accept(sockfd, addr, addrlen)) > -1) {
+ (*counter)++;
+ ldebug("inflight incremented, now %d", *counter);
+ }
+ return ret;
+}
+
void
slowcgi_accept(int fd, short events, void *arg)
{
@@ -383,8 +408,8 @@ slowcgi_accept(int fd, short events, void *arg)
c = NULL;
len = sizeof(ss);
- s = accept(fd, (struct sockaddr *)&ss, &len);
- if (s == -1) {
+ if ((s = accept_reserve(fd, (struct sockaddr *)&ss,
+ &len, FD_RESERVE, &cgi_inflight)) == -1) {
switch (errno) {
case EINTR:
case EWOULDBLOCK:
@@ -408,12 +433,14 @@ slowcgi_accept(int fd, short events, void *arg)
if (c == NULL) {
lwarn("cannot calloc request");
close(s);
+ cgi_inflight--;
return;
}
requests = calloc(1, sizeof(*requests));
if (requests == NULL) {
lwarn("cannot calloc requests");
close(s);
+ cgi_inflight--;
free(c);
return;
}
@@ -422,6 +449,7 @@ slowcgi_accept(int fd, short events, void *arg)
c->buf_len = 0;
c->request_started = 0;
c->stdin_fd_closed = c->stdout_fd_closed = c->stderr_fd_closed = 0;
+ c->inflight_fds_accounted = 0;
TAILQ_INIT(&c->response_head);
TAILQ_INIT(&c->stdin_head);
@@ -792,6 +820,8 @@ exec_cgi(struct request *c)
lerr(1, "socketpair");
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s_err) == -1)
lerr(1, "socketpair");
+ cgi_inflight--;
+ c->inflight_fds_accounted = 1;
ldebug("fork: %s", c->script_name);
switch (pid = fork()) {
@@ -1033,6 +1063,8 @@ cleanup_request(struct request *c)
break;
}
}
+ if (! c->inflight_fds_accounted)
+ cgi_inflight--;
free(c);
}