From 31e2a93e08a0e68d71e37f9697564d26936b5819 Mon Sep 17 00:00:00 2001 Message-Id: <31e2a93e08a0e68d71e37f9697564d26936b5819.1714637962.git.mdw@distorted.org.uk> From: Mark Wooding Date: Sun, 15 Feb 2009 11:39:46 +0000 Subject: [PATCH] Set resource limits on the server to prevent more than FD_SETSIZE files being opened. (It's not unusual for them to be set like this anyway, but this change guarantees it.) Organization: Straylight/Edgeware From: Richard Kettlewell event.c also checks for FDs being in range. --- lib/event.c | 2 ++ lib/trackdb.c | 9 ++++++--- server/disorder-server.h | 1 + server/disorderd.c | 13 +++++++++++++ server/play.c | 3 ++- server/server.c | 10 ++++++++++ 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/lib/event.c b/lib/event.c index 38cb741..ee25024 100644 --- a/lib/event.c +++ b/lib/event.c @@ -311,6 +311,8 @@ int ev_fd(ev_source *ev, D(("registering %s fd %d callback %p %p", modenames[mode], fd, (void *)callback, u)); + if(fd >= FD_SETSIZE) + return -1; assert(mode < ev_nmodes); if(ev->mode[mode].nfds >= ev->mode[mode].fdslots) { ev->mode[mode].fdslots = (ev->mode[mode].fdslots diff --git a/lib/trackdb.c b/lib/trackdb.c index 2218078..e1bbfc8 100644 --- a/lib/trackdb.c +++ b/lib/trackdb.c @@ -1400,7 +1400,9 @@ void trackdb_stats_subprocess(ev_source *ev, pid = subprogram(ev, p[1], "disorder-stats", (char *)0); xclose(p[1]); ev_child(ev, pid, 0, stats_finished, d); - ev_reader_new(ev, p[0], stats_read, stats_error, d, "disorder-stats reader"); + if(!ev_reader_new(ev, p[0], stats_read, stats_error, d, + "disorder-stats reader")) + fatal(0, "ev_reader_new for disorder-stats reader failed"); } /** @brief Parse a track name part preference @@ -1756,8 +1758,9 @@ int trackdb_request_random(ev_source *ev, choose_callback = callback; choose_output.nvec = 0; choose_complete = 0; - ev_reader_new(ev, p[0], choose_readable, choose_read_error, 0, - "disorder-choose reader"); /* owns p[0] */ + if(!ev_reader_new(ev, p[0], choose_readable, choose_read_error, 0, + "disorder-choose reader")) /* owns p[0] */ + fatal(0, "ev_reader_new for disorder-choose reader failed"); ev_child(ev, choose_pid, 0, choose_exited, 0); /* owns the subprocess */ return 0; } diff --git a/server/disorder-server.h b/server/disorder-server.h index 1a52e25..4eb58e4 100644 --- a/server/disorder-server.h +++ b/server/disorder-server.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include diff --git a/server/disorderd.c b/server/disorderd.c index e03fa42..2342c3c 100644 --- a/server/disorderd.c +++ b/server/disorderd.c @@ -174,6 +174,7 @@ static void fix_path(void) { int main(int argc, char **argv) { int n, background = 1, logsyslog = 0; const char *pidfile = 0; + struct rlimit rl[1]; set_progname(argv); mem_init(); @@ -208,6 +209,18 @@ int main(int argc, char **argv) { srand(time(0)); /* don't start the same every time */ /* gcrypt initialization */ gcry_control(GCRYCTL_INIT_SECMEM, 1); + /* make sure we can't have more than FD_SETSIZE files open (event.c does + * check but this provides an additional line of defence) */ + if(getrlimit(RLIMIT_NOFILE, rl) < 0) + fatal(errno, "getrlimit RLIMIT_NOFILE"); + if(rl->rlim_cur > FD_SETSIZE) { + rl->rlim_cur = FD_SETSIZE; + if(setrlimit(RLIMIT_NOFILE, rl) < 0) + fatal(errno, "setrlimit to reduce RLIMIT_NOFILE to %lu", + (unsigned long)rl->rlim_cur); + info("set RLIM_NOFILE to %lu", (unsigned long)rl->rlim_cur); + } else + info("RLIM_NOFILE is %lu", (unsigned long)rl->rlim_cur); /* create event loop */ ev = ev_new(); if(ev_child_setup(ev)) fatal(0, "ev_child_setup failed"); diff --git a/server/play.c b/server/play.c index c60d932..93a7f48 100644 --- a/server/play.c +++ b/server/play.c @@ -128,7 +128,8 @@ void speaker_setup(ev_source *ev) { /* Wait for the speaker to be ready */ speaker_recv(speaker_fd, &sm); nonblock(speaker_fd); - ev_fd(ev, ev_read, speaker_fd, speaker_readable, 0, "speaker read"); + if(ev_fd(ev, ev_read, speaker_fd, speaker_readable, 0, "speaker read") < 0) + fatal(0, "error registering speaker socket fd"); } void speaker_reload(void) { diff --git a/server/server.c b/server/server.c index 18f6851..2874357 100644 --- a/server/server.c +++ b/server/server.c @@ -1802,8 +1802,18 @@ static int listen_callback(ev_source *ev, c->ev = ev; c->w = ev_writer_new(ev, fd, writer_error, c, "client writer"); + if(!c->w) { + error(0, "ev_writer_new for file inbound connection (fd=%d) failed", + fd); + close(fd); + return 0; + } c->r = ev_reader_new(ev, fd, redirect_reader_callback, reader_error, c, "client reader"); + if(!c->r) + /* Main reason for failure is the FD is too big and that will already have + * been handled */ + fatal(0, "ev_reader_new for file inbound connection (fd=%d) failed", fd); ev_tie(c->r, c->w); c->fd = fd; c->reader = reader_callback; -- [mdw]