chiark / gitweb /
Set resource limits on the server to prevent more than FD_SETSIZE
authorRichard Kettlewell <rjk@greenend.org.uk>
Sun, 15 Feb 2009 11:39:46 +0000 (11:39 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sun, 15 Feb 2009 11:39:46 +0000 (11:39 +0000)
files being opened.  (It's not unusual for them to be set like this
anyway, but this change guarantees it.)

event.c also checks for FDs being in range.

lib/event.c
lib/trackdb.c
server/disorder-server.h
server/disorderd.c
server/play.c
server/server.c

index 38cb741ce406cb7154c17e196885255e25bd6123..ee25024c594369c8818471dd6b2b07a5a2ed778f 100644 (file)
@@ -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
index 2218078a1706e69b9a6ebd5e0c1c41fdf30201ef..e1bbfc881bbd81ccfbedf6a72d1d1f17b46a89f9 100644 (file)
@@ -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;
 }
index 1a52e25172bf1be83d6afacdc2de47fa160c2057..4eb58e45845e9f34689104166d8272888cc7fd87 100644 (file)
@@ -42,6 +42,7 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/un.h>
+#include <sys/resource.h>
 #include <syslog.h>
 #include <time.h>
 #include <unistd.h>
index e03fa42dd71200337f98e41f085cbaa4e721e4bd..2342c3c07e63fd67b620a667a3c224a506933eb4 100644 (file)
@@ -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");
index c60d9325b9a2ca96de83da01d4c6ea9a7deea09d..93a7f48fa8996f8a8d6b456245b652f477c16fdc 100644 (file)
@@ -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) {
index 18f6851ff6f741556b6b257f3dae529113369ab8..2874357a4e8959f7ceef798a093feb340d1d577c 100644 (file)
@@ -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;