diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2009-01-30 17:34:59 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2009-01-30 17:34:59 +0000 |
commit | 2ad85d8d97e961839ddcb838af1f52104af1d030 (patch) | |
tree | b34985d3486b1b1f122f1eb9004b267289652820 /usr.sbin | |
parent | ae280d1b5f9990fabe1466ff8e7f61df8f618db5 (diff) |
bump descriptors limit to the max and set the maximum connections count to
three quarters of that limit (a session typically has 3 descriptors). when
we hit that limit, we stop accepting connections, and when client closes a
session, we start accepting connections again. this prevents us from going
into a session that is likely to fail because of scarce resources.
idea discussed with jacekm@, code mostly ripped from relayd
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/smtpd/smtp.c | 12 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtp_session.c | 8 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.c | 20 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 3 |
4 files changed, 34 insertions, 9 deletions
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c index 0f5f24c18fb..a2338ab4353 100644 --- a/usr.sbin/smtpd/smtp.c +++ b/usr.sbin/smtpd/smtp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp.c,v 1.19 2009/01/30 16:37:52 gilles Exp $ */ +/* $OpenBSD: smtp.c,v 1.20 2009/01/30 17:34:58 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -698,7 +698,7 @@ smtp_accept(int fd, short event, void *p) log_debug("smtp_accept: incoming client on listener: %p", l); len = sizeof(struct sockaddr_storage); if ((s_fd = accept(l->fd, (struct sockaddr *)&ss, &len)) == -1) { - event_add(&l->ev, NULL); + event_del(&l->ev); return; } @@ -709,10 +709,18 @@ smtp_accept(int fd, short event, void *p) s->s_fd = s_fd; s->s_tm = time(NULL); + s->s_env = l->env; + s->s_l = l; + (void)memcpy(&s->s_ss, &ss, sizeof(s->s_ss)); session_init(l, s); event_add(&l->ev, NULL); + + s_smtp.clients++; + + if (s_smtp.clients == s->s_env->sc_maxconn) + event_del(&l->ev); } void diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c index 1340cc703e5..3b1a6552371 100644 --- a/usr.sbin/smtpd/smtp_session.c +++ b/usr.sbin/smtpd/smtp_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp_session.c,v 1.48 2009/01/30 16:37:52 gilles Exp $ */ +/* $OpenBSD: smtp_session.c,v 1.49 2009/01/30 17:34:58 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -748,12 +748,8 @@ void session_init(struct listener *l, struct session *s) { s->s_state = S_INIT; - s->s_env = l->env; - s->s_l = l; s->s_id = queue_generate_id(); - s_smtp.clients++; - if ((s->s_bev = bufferevent_new(s->s_fd, session_read, session_write, session_error, s)) == NULL) fatalx("session_init: bufferevent_new failed"); @@ -912,6 +908,8 @@ session_destroy(struct session *s) close(s->s_fd); s_smtp.clients--; + if (s_smtp.clients < s->s_env->sc_maxconn) + event_add(&s->s_l->ev, NULL); if (s->s_bev != NULL) { bufferevent_free(s->s_bev); diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index 6f13c500d39..4dbfcaa5c0c 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.28 2009/01/30 10:03:29 form Exp $ */ +/* $OpenBSD: smtpd.c,v 1.29 2009/01/30 17:34:58 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -25,6 +25,7 @@ #include <sys/wait.h> #include <sys/stat.h> #include <sys/uio.h> +#include <sys/resource.h> #include <bsd_auth.h> #include <err.h> @@ -591,6 +592,7 @@ main(int argc, char *argv[]) struct event ev_sigchld; struct event ev_sighup; struct timeval tv; + struct rlimit rl; struct peer peers[] = { { PROC_CONTROL, parent_dispatch_control }, { PROC_LKA, parent_dispatch_lka }, @@ -659,6 +661,22 @@ main(int argc, char *argv[]) log_info("startup%s", (debug > 1)?" [debug mode]":""); + if (getrlimit(RLIMIT_NOFILE, &rl) == -1) + fatal("smtpd: failed to get resource limit"); + + log_debug("smtpd: max open files %lld", rl.rlim_max); + + /* + * Allow the maximum number of open file descriptors for this + * login class (which should be the class "daemon" by default). + */ + rl.rlim_cur = rl.rlim_max; + if (setrlimit(RLIMIT_NOFILE, &rl) == -1) + fatal("smtpd: failed to set resource limit"); + + env.sc_maxconn = (rl.rlim_cur / 4) * 3; + log_debug("smtpd: will accept at most %d clients", env.sc_maxconn); + init_peers(&env); /* start subprocesses */ diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index 60b50aa413d..2c6da0c217d 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.63 2009/01/30 16:37:52 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.64 2009/01/30 17:34:58 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -624,6 +624,7 @@ struct smtpd { #define SMTPD_SMTP_PAUSED 0x00000010 u_int32_t sc_flags; struct timeval sc_qintval; + u_int32_t sc_maxconn; struct event sc_ev; int sc_pipes[PROC_COUNT] [PROC_COUNT][2]; |