On Mon, Jun 11, 2012 at 12:33:28PM +0200, Peter Bex wrote:
Currently a patch is being developed. In the meanwhile an effective
workaround is to limit the maximum number of open descriptors using
the Unix ulimit -n command.
For those feeling adventurous, please test the attached patch. We are
currently debating whether it should be applied, but unsure because
there could be some potential portability problems with it as well as
the fact that it's a reasonably large change to a core component of
Chicken which is pretty subtle.
It would be especially useful if people using anything *other* than
Linux or BSD could report back success or failure.
Cheers,
Peter
--
http://sjamaan.ath.cx
--
The process of preparing programs for a digital computer
is especially attractive, not only because it can be economically
and scientifically rewarding, but also because it can be an aesthetic
experience much like composing poetry or music.
-- Donald Knuth
From 52e581254a713daa2f19693108af35a859ec7ebd Mon Sep 17 00:00:00 2001
From: Peter Bex peter@xs4all.nl
Date: Fri, 8 Jun 2012 22:08:40 +0200
Subject: [PATCH] Fix scheduler so it can handle file descriptors over
FD_SETSIZE (which occurs in practice on systems where
ulimit -n has a higher value)
---
NEWS |1 +
scheduler.scm | 98 ++--
2 files changed, 60 insertions(+), 39 deletions(-)
diff --git a/NEWS b/NEWS
index 7ec6431..725dddc 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@
- on 64-bit machines the random procedure no longer truncates result
values (which caused very nonrandom results for very large values).
Note that random shouldn't be used for security-critical code.
+ - Fixed select()-calls to accommodate more than FD_SETSIZE open files.
- Build system
- version information has been moved into a separate unit to make the
diff --git a/scheduler.scm b/scheduler.scm
index e3a96bc..c28ed16 100644
--- a/scheduler.scm
+++ b/scheduler.scm
@@ -31,9 +31,8 @@
(hide ready-queue-head ready-queue-tail ##sys#timeout-list
##sys#update-thread-state-buffer ##sys#restore-thread-state-buffer
remove-from-ready-queue ##sys#unblock-threads-for-i/o
##sys#force-primordial
- fdset-input-set fdset-output-set fdset-clear
- fdset-select-timeout fdset-set fdset-test
- create-fdset stderr
+ current-fdset-size fd-iset fd-oset fdset-extend fdset-clear make-fdset
+fdset-select-timeout fdset-set fdset-test create-fdset stderr
##sys#clear-i/o-state-for-thread! ##sys#abandon-mutexes)
(not inline ##sys#interrupt-hook)
(unsafe)
@@ -74,9 +73,16 @@ C_word C_msleep(C_word ms) {
return C_SCHEME_TRUE;
}
#endif
+/* These two should be defined by select.h, but are not standardized... */
+#ifndef howmany
+#definehowmany(x, y) (((x)+((y)-1))/(y))
+#endif
+#ifndef NFDBITS
+#define NFDBITS (sizeof (fd_mask) * 8)
+#endif
+
static fd_set C_fdset_input, C_fdset_output;
-#define C_fd_test_input(fd) C_mk_bool(FD_ISSET(C_unfix(fd), C_fdset_input))
-#define C_fd_test_output(fd) C_mk_bool(FD_ISSET(C_unfix(fd), C_fdset_output))
+#define C_fd_test(fd,set) C_mk_bool(FD_ISSET(C_unfix(fd), (fd_set
*)C_data_pointer(set)))
EOF
) )
@@ -344,46 +350,61 @@ EOF
(define ##sys#fd-list '()) ; ((FD1 THREAD1 ...) ...)
+(define current-fdset-size 64)
+(define fd-iset (make-fdset current-fdset-size))
+(define fd-oset (make-fdset current-fdset-size))
+
(define (create-fdset)
- (fdset-clear)
- (let loop ((lst ##sys#fd-list))
-(unless (null? lst)
- (let ((fd (caar lst)))
- (for-each
-(lambda (t)
- (let ((p (##sys#slot t 11)))
-(fdset-set fd (cdr p
-(cdar lst))
- (loop (cdr lst))
+ (let* ((max (foldl (lambda (max x) (fxmax max (car x))) 0 ##sys#fd-list))
+(size (let lp ((s current-fdset-size)) ; Find next power of two
+(if (fx max s) (lp (fxshl s 1)) s
+(when (fx size current-fdset-size) ; Adjust set sizes if neccessary
+ (set! current-fdset-size size)
+ (set! fd-iset (make-fdset size))
+ (set! fd-oset (make-fdset size)))
+(fdset-clear fd-iset)
+(fdset-clear fd-oset)
+(let loop ((lst ##sys#fd-list))
+ (unless (null? lst)
+ (let ((fd (caar lst)))
+ (for-each
+ (lambda (t)
+(let ((p (##sys#slot t 11)))
+ (fdset-set fd (cdr p
+ (cdar lst))
+ (loop (cdr lst)
+max))
(define fdset-select-timeout
- (foreign-lambda* int ([bool to] [double tm])
+ (foreign-lambda* int ((int maxfd) (bool to) (double tm)
+(scheme-pointer iset) (scheme-pointer oset))
struct timeval timeout;
timeout.tv_sec = tm / 1000;
timeout.tv_usec = fmod(tm, 1000) * 1000;
-C_return(select(FD_SETSIZE, C_fdset_input, C_fdset_output, NULL, to ?
timeout : NULL));) )
+