1.0.42.45: more descriptive errors for exceeding FD_SETSIZE
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 19 Sep 2010 21:33:31 +0000 (21:33 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 19 Sep 2010 21:33:31 +0000 (21:33 +0000)
 Instead of a type-error whose meaning is pretty opaque to an average
 user, signal an error with a descriptive message.

 Add bug numbers to the previous select()/poll() changes in NEWS.

NEWS
src/code/serve-event.lisp
src/code/unix.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index ce063ac..653806a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,7 @@
 ;;;; -*- coding: utf-8; fill-column: 78 -*-
 changes relative to sbcl-1.0.42
   * incompatible change: FD-STREAMS no longer participate in the serve-event
-    event-loop by default.
+    event-loop by default. (lp#316072)
     ** In addition to streams created by explicit calls to MAKE-FD-STREAM this
        affects streams from CL:OPEN.
     ** Streams from SOCKET-MAKE-STREAM still participate in serve-event by
@@ -17,10 +17,9 @@ changes relative to sbcl-1.0.42
   * enhancement: symbols are printed using fully qualified names in several
     error and warning messages which are often associated with package
     conflicts or mixups (lp#622789, thanks to Attila Lendvai)
-  * optimization: where available, use poll(2) instead of select(2) to check
-    for blocking IO on a single FD.
   * bug fix: SB-BSD-SOCKETS:SOCKET-CONNECT was not thread safe. (lp#505497,
     thanks to Andrew Golding)
+  * bug fix: reading /proc files on Linux works. (lp#425199)
   * bug fix: DOTIMES accepted literal non-integer reals. (lp#619393, thanks to
     Roman Marynchak)
   * bug fix: WRITE-TO-STRING compiler macro binding special variable names,
@@ -56,6 +55,8 @@ changes relative to sbcl-1.0.42
   * bug fix: workaround for compiler hang in ORDER-UVL-SETS (lp#308914)
   * bug fix: evaluation in debugger REPL works using the global context when
     in frames that do not have sufficient debug information.
+  * bug fix: exceeding FD_SETSIZE limit now results in an sensible error
+    (lp#316068)
 
 changes in sbcl-1.0.42 relative to sbcl-1.0.41
   * build changes
index 508d465..e3563e6 100644 (file)
@@ -72,6 +72,8 @@
   (unless (member direction '(:input :output))
     ;; FIXME: should be TYPE-ERROR?
     (error "Invalid direction ~S, must be either :INPUT or :OUTPUT" direction))
+  (unless (<= 0 fd (1- sb!unix:fd-setsize))
+    (error "Cannot add an FD handler for ~D: not under FD_SETSIZE limit." fd))
   (let ((handler (make-handler direction fd function)))
     (with-descriptor-handlers
       (push handler *descriptor-handlers*))
index 2ea6ee9..37d715f 100644 (file)
@@ -625,6 +625,14 @@ corresponds to NAME, or NIL if there is none."
 \f
 ;;;; sys/select.h
 
+(defmacro with-fd-setsize ((n) &body body)
+  `(let ((,n (if (< 0 ,n fd-setsize)
+                 ,n
+                 (error "Cannot select(2) on ~D: above FD_SETSIZE limit."
+                        (1- num-descriptors)))))
+     (declare (type (integer 0 #.fd-setsize) ,n))
+     ,@body))
+
 ;;;; FIXME: Why have both UNIX-SELECT and UNIX-FAST-SELECT?
 
 ;;; Perform the UNIX select(2) system call.
@@ -632,24 +640,25 @@ corresponds to NAME, or NIL if there is none."
 (defun unix-fast-select (num-descriptors
                          read-fds write-fds exception-fds
                          timeout-secs timeout-usecs)
-  (declare (type (integer 0 #.fd-setsize) num-descriptors)
+  (declare (type integer num-descriptors)
            (type (or (alien (* (struct fd-set))) null)
                  read-fds write-fds exception-fds)
            (type (or null (unsigned-byte 31)) timeout-secs timeout-usecs))
-  (flet ((select (tv-sap)
-           (int-syscall ("select" int (* (struct fd-set)) (* (struct fd-set))
-                                  (* (struct fd-set)) (* (struct timeval)))
-                        num-descriptors read-fds write-fds exception-fds
-                        tv-sap)))
-    (cond ((or timeout-secs timeout-usecs)
-           (with-alien ((tv (struct timeval)))
-             (setf (slot tv 'tv-sec) (or timeout-secs 0))
-             (setf (slot tv 'tv-usec) (or timeout-usecs 0))
-             (select (alien-sap (addr tv)))))
-          (t
-           (unless *interrupts-enabled*
-             (note-dangerous-wait "select(2)"))
-           (select (int-sap 0))))))
+  (with-fd-setsize (num-descriptors)
+    (flet ((select (tv-sap)
+             (int-syscall ("select" int (* (struct fd-set)) (* (struct fd-set))
+                                    (* (struct fd-set)) (* (struct timeval)))
+                          num-descriptors read-fds write-fds exception-fds
+                          tv-sap)))
+      (cond ((or timeout-secs timeout-usecs)
+             (with-alien ((tv (struct timeval)))
+               (setf (slot tv 'tv-sec) (or timeout-secs 0))
+               (setf (slot tv 'tv-usec) (or timeout-usecs 0))
+               (select (alien-sap (addr tv)))))
+            (t
+             (unless *interrupts-enabled*
+               (note-dangerous-wait "select(2)"))
+             (select (int-sap 0)))))))
 
 ;;; UNIX-SELECT accepts sets of file descriptors and waits for an event
 ;;; to happen on one of them or to time out.
@@ -680,35 +689,36 @@ corresponds to NAME, or NIL if there is none."
 ;;; they are ready for reading and writing. See the UNIX Programmer's
 ;;; Manual for more information.
 (defun unix-select (nfds rdfds wrfds xpfds to-secs &optional (to-usecs 0))
-  (declare (type (integer 0 #.fd-setsize) nfds)
+  (declare (type integer nfds)
            (type unsigned-byte rdfds wrfds xpfds)
            (type (or (unsigned-byte 31) null) to-secs)
            (type (unsigned-byte 31) to-usecs)
            (optimize (speed 3) (safety 0) (inhibit-warnings 3)))
-  (with-alien ((tv (struct timeval))
-               (rdf (struct fd-set))
-               (wrf (struct fd-set))
-               (xpf (struct fd-set)))
-    (cond (to-secs
-           (setf (slot tv 'tv-sec) to-secs
-                 (slot tv 'tv-usec) to-usecs))
-          ((not *interrupts-enabled*)
-           (note-dangerous-wait "select(2)")))
-    (num-to-fd-set rdf rdfds)
-    (num-to-fd-set wrf wrfds)
-    (num-to-fd-set xpf xpfds)
-    (macrolet ((frob (lispvar alienvar)
-                 `(if (zerop ,lispvar)
-                      (int-sap 0)
-                      (alien-sap (addr ,alienvar)))))
-      (syscall ("select" int (* (struct fd-set)) (* (struct fd-set))
-                         (* (struct fd-set)) (* (struct timeval)))
-               (values result
-                       (fd-set-to-num nfds rdf)
-                       (fd-set-to-num nfds wrf)
-                       (fd-set-to-num nfds xpf))
-               nfds (frob rdfds rdf) (frob wrfds wrf) (frob xpfds xpf)
-               (if to-secs (alien-sap (addr tv)) (int-sap 0))))))
+  (with-fd-setsize (nfds)
+    (with-alien ((tv (struct timeval))
+                 (rdf (struct fd-set))
+                 (wrf (struct fd-set))
+                 (xpf (struct fd-set)))
+      (cond (to-secs
+             (setf (slot tv 'tv-sec) to-secs
+                   (slot tv 'tv-usec) to-usecs))
+            ((not *interrupts-enabled*)
+             (note-dangerous-wait "select(2)")))
+      (num-to-fd-set rdf rdfds)
+      (num-to-fd-set wrf wrfds)
+      (num-to-fd-set xpf xpfds)
+      (macrolet ((frob (lispvar alienvar)
+                   `(if (zerop ,lispvar)
+                        (int-sap 0)
+                        (alien-sap (addr ,alienvar)))))
+        (syscall ("select" int (* (struct fd-set)) (* (struct fd-set))
+                           (* (struct fd-set)) (* (struct timeval)))
+                 (values result
+                         (fd-set-to-num nfds rdf)
+                         (fd-set-to-num nfds wrf)
+                         (fd-set-to-num nfds xpf))
+                 nfds (frob rdfds rdf) (frob wrfds wrf) (frob xpfds xpf)
+                 (if to-secs (alien-sap (addr tv)) (int-sap 0)))))))
 
 ;;; Lisp-side implmentations of FD_FOO macros. Abandon all hope who enters
 ;;; here...
index 9714821..a43766b 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.42.44"
+"1.0.42.45"