Server won't die for out of handles.
authorviric@llimona
Thu, 05 Apr 2007 22:20:38 +0200
changeset 94 aefdd4d9cbab
parent 93 332574eacf8a
child 95 d31aaee661d1
Server won't die for out of handles.
Changelog
server.c
--- a/Changelog	Thu Apr 05 21:48:11 2007 +0200
+++ b/Changelog	Thu Apr 05 22:20:38 2007 +0200
@@ -20,6 +20,11 @@
  - Store the 'times()' for the run tasks.
  - Use a better system than mkstemp() for finding output files, so we can add
    .gz to the gzipped outputs.
+v0.3.2:
+ -* Fixed the $POSIXLY_CORRECT bug finally
+ -* Slightly better makefile and man page
+ -* The server should never run out of handles - simply block the client
+ -* Added an error reporting system.
 v0.3.1:
  -* Fixed a bug with $POSIXLY_CORRECT being passed to the jobs. This break the
    gentoo emerge jobs.
--- a/server.c	Thu Apr 05 21:48:11 2007 +0200
+++ b/server.c	Thu Apr 05 22:20:38 2007 +0200
@@ -7,11 +7,14 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/select.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <sys/un.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <limits.h>
 
 #include <stdio.h>
 
@@ -48,6 +51,37 @@
 static struct Client_conn client_cs[MAXCONN];
 static int nconnections;
 static char *path;
+static int max_descriptors;
+
+
+static int get_max_descriptors()
+{
+    const int MARGIN = 5; /* stdin, stderr, listen socket, and whatever */
+    int max;
+    struct rlimit rlim;
+    int res;
+
+    max = MAXCONN;
+    if (max > FD_SETSIZE)
+        max = FD_SETSIZE;
+
+    /* I'd like to use OPEN_MAX or NR_OPEN, but I don't know if any
+     * of them is POSIX compliant */
+
+    res = getrlimit(RLIMIT_NOFILE, &rlim);
+    if (res != 0)
+        warning("getrlimit for open files");
+    else
+    {
+        if (max > rlim.rlim_cur)
+            max = rlim.rlim_cur;
+    }
+
+    if (max - MARGIN < 1)
+        error("Too few opened descriptors available");
+
+    return max - MARGIN;
+}
 
 void server_main(int notify_fd, char *_path)
 {
@@ -55,6 +89,8 @@
     struct sockaddr_un addr;
     int res;
 
+    max_descriptors = get_max_descriptors();
+
     path = _path;
 
     nconnections = 0;
@@ -99,8 +135,14 @@
     while (keep_loop)
     {
         FD_ZERO(&readset);
-        FD_SET(ls,&readset);
-        maxfd = ls;
+        maxfd = 0;
+        /* If we can accept more connections, go on.
+         * Otherwise, the system block them (no accept will be done). */
+        if (nconnections < max_descriptors)
+        {
+            FD_SET(ls,&readset);
+            maxfd = ls;
+        }
         for(i=0; i< nconnections; ++i)
         {
             FD_SET(client_cs[i].socket, &readset);