~ chicken-core (chicken-5) 93517411bfad107871a11cdc4ecc1a9a12079290
commit 93517411bfad107871a11cdc4ecc1a9a12079290 Author: Peter Bex <peter.bex@xs4all.nl> AuthorDate: Sun Jul 17 15:56:55 2011 +0200 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Sun Jul 17 23:30:29 2011 +0200 Change port procedures which try to read or write (or access the underlying descriptor) to not just check their arguments for being a port, but also check that the port is still open. diff --git a/extras.scm b/extras.scm index 31309c24..e790fff8 100644 --- a/extras.scm +++ b/extras.scm @@ -84,7 +84,7 @@ (let* ([parg (pair? args)] [p (if parg (car args) ##sys#standard-input)] [limit (and parg (pair? (cdr args)) (cadr args))]) - (##sys#check-port p 'read-line) + (##sys#check-port* p 'read-line) (cond ((##sys#slot (##sys#slot p 2) 8) => (lambda (rl) (rl p limit))) (else (let* ((buffer-len (if limit limit 256)) @@ -175,7 +175,7 @@ (else (fx+ n2 m))) ))))))) (define (read-string! n dest #!optional (port ##sys#standard-input) (start 0)) - (##sys#check-port port 'read-string!) + (##sys#check-port* port 'read-string!) (##sys#check-string dest 'read-string!) (when n (##sys#check-exact n 'read-string!) @@ -188,7 +188,7 @@ (define ##sys#read-string/port (lambda (n p) - (##sys#check-port p 'read-string) + (##sys#check-port* p 'read-string) (cond (n (##sys#check-exact n 'read-string) (let* ((str (##sys#make-string n)) (n2 (##sys#read-string! n str p 0)) ) @@ -230,7 +230,7 @@ (define read-token (lambda (pred . port) (let ([port (optional port ##sys#standard-input)]) - (##sys#check-port port 'read-token) + (##sys#check-port* port 'read-token) (let ([out (open-output-string)]) (let loop () (let ([c (##sys#peek-char-0 port)]) @@ -256,7 +256,7 @@ ;;; Binary I/O (define (read-byte #!optional (port ##sys#standard-input)) - (##sys#check-port port 'read-byte) + (##sys#check-port* port 'read-byte) (let ((x (##sys#read-char-0 port))) (if (eof-object? x) x @@ -264,7 +264,7 @@ (define (write-byte byte #!optional (port ##sys#standard-output)) (##sys#check-exact byte 'write-byte) - (##sys#check-port port 'write-byte) + (##sys#check-port* port 'write-byte) (##sys#write-char-0 (integer->char byte) port) ) @@ -575,7 +575,7 @@ (define fprintf0 (lambda (loc port msg args) - (when port (##sys#check-port port loc)) + (when port (##sys#check-port* port loc)) (let ((out (if (and port (##sys#tty-port? port)) port (open-output-string)))) diff --git a/library.scm b/library.scm index 63c6c964..c08a43a1 100644 --- a/library.scm +++ b/library.scm @@ -3009,11 +3009,13 @@ EOF (for-each (cut ##sys#print <> #f ##sys#standard-output) lst) ) (define (print . args) + (##sys#check-port* ##sys#standard-output 'print) (*print-each args) (##sys#write-char-0 #\newline ##sys#standard-output) (void) ) (define (print* . args) + (##sys#check-port* ##sys#standard-output 'print) (*print-each args) (##sys#flush-output ##sys#standard-output) (void) ) @@ -3689,7 +3691,7 @@ EOF (define (print-call-chain #!optional (port ##sys#standard-output) (start 0) (thread ##sys#current-thread) (header "\n\tCall history:\n") ) - (##sys#check-port port 'print-call-chain) + (##sys#check-port* port 'print-call-chain) (##sys#check-exact start 'print-call-chain) (##sys#check-string header 'print-call-chain) (let ((ct (##sys#get-call-chain start thread))) diff --git a/posixunix.scm b/posixunix.scm index 82adbbb2..3e578d92 100644 --- a/posixunix.scm +++ b/posixunix.scm @@ -1757,7 +1757,7 @@ EOF (##sys#error 'set-buffering-mode! "cannot set buffering mode" port mode size) ) ) ) ) (define (terminal-port? port) - (##sys#check-port port 'terminal-port?) + (##sys#check-port* port 'terminal-port?) (let ([fp (##sys#peek-unsigned-integer port 0)]) (and (not (eq? 0 fp)) (##core#inline "C_tty_portp" port) ) ) ) diff --git a/posixwin.scm b/posixwin.scm index a1e976ab..28f8c5fa 100644 --- a/posixwin.scm +++ b/posixwin.scm @@ -1461,7 +1461,7 @@ EOF (ex0 (if (pair? code) (car code) 0)) ) ) ) (define (terminal-port? port) - (##sys#check-port port 'terminal-port?) + (##sys#check-port* port 'terminal-port?) (let ([fp (##sys#peek-unsigned-integer port 0)]) (and (not (eq? 0 fp)) (##core#inline "C_tty_portp" port) ) ) ) diff --git a/srfi-4.scm b/srfi-4.scm index 83df6718..c41a261c 100644 --- a/srfi-4.scm +++ b/srfi-4.scm @@ -642,7 +642,7 @@ EOF (define (write-u8vector v #!optional (port ##sys#standard-output) (from 0) (to (u8vector-length v))) (##sys#check-structure v 'u8vector 'write-u8vector) - (##sys#check-port port 'write-u8vector) + (##sys#check-port* port 'write-u8vector) (do ((i from (fx+ i 1))) ((fx>= i to)) (##sys#write-char-0 @@ -650,7 +650,7 @@ EOF port) ) ) (define (read-u8vector! n dest #!optional (port ##sys#standard-input) (start 0)) - (##sys#check-port port 'read-u8vector!) + (##sys#check-port* port 'read-u8vector!) (##sys#check-exact start 'read-u8vector!) (##sys#check-structure dest 'u8vector 'read-u8vector!) (let ((dest (##sys#slot dest 1))) @@ -670,7 +670,7 @@ EOF (##core#inline "C_substring_copy" str str2 0 n 0) str2) ) ) (lambda (#!optional n (p ##sys#standard-input)) - (##sys#check-port p 'read-u8vector) + (##sys#check-port* p 'read-u8vector) (cond (n (##sys#check-exact n 'read-u8vector) (let* ((str (##sys#allocate-vector n #t #f #t)) (n2 (##sys#read-string! n str p 0)) ) diff --git a/tcp.scm b/tcp.scm index c8e1bd76..18530924 100644 --- a/tcp.scm +++ b/tcp.scm @@ -629,7 +629,7 @@ EOF (error '##sys#tcp-port->fileno "argument does not appear to be a TCP port" p)))) (define (tcp-addresses p) - (##sys#check-port p 'tcp-addresses) + (##sys#check-port* p 'tcp-addresses) (let ((fd (##sys#tcp-port->fileno p))) (values (or (##net#getsockname fd) @@ -642,7 +642,7 @@ EOF (##sys#string-append "cannot compute remote address - " strerror) p) ) ) ) ) (define (tcp-port-numbers p) - (##sys#check-port p 'tcp-port-numbers) + (##sys#check-port* p 'tcp-port-numbers) (let ((fd (##sys#tcp-port->fileno p))) (values (or (##net#getsockport fd) @@ -665,7 +665,7 @@ EOF port) ) (define (tcp-abandon-port p) - (##sys#check-port p 'tcp-abandon-port) + (##sys#check-port* p 'tcp-abandon-port) (##sys#setislot (##sys#port-data p) (if (##sys#slot p 1) 1 2) diff --git a/tests/port-tests.scm b/tests/port-tests.scm index 72795418..ee562c20 100644 --- a/tests/port-tests.scm +++ b/tests/port-tests.scm @@ -1,4 +1,4 @@ -(require-extension srfi-1 ports utils) +(require-extension srfi-1 ports utils srfi-4 extras tcp posix) (define *text* #<<EOF this is a test @@ -99,3 +99,84 @@ EOF (copy-port (current-input-port) (current-output-port))))))) (delete-file "compiler.scm.2") + +(define-syntax check + (syntax-rules () + ((_ (expr-head expr-rest ...)) + (check 'expr-head (expr-head expr-rest ...))) + ((_ name expr) + (let ((okay (list 'okay))) + (assert + (eq? okay + (condition-case + (begin (print* name "...") + (flush-output) + (let ((output expr)) + (printf "FAIL [ ~S ]\n" output))) + ((exn i/o file) (printf "OK\n") okay)))))))) + +(define proc (process-fork (lambda () (tcp-accept (tcp-listen 8080))))) + +(on-exit (lambda () (handle-exceptions exn #f (process-signal proc)))) + +(print "\n\nProcedures check on TCP ports being closed\n") + +(receive (in out) + (let lp () + (condition-case (tcp-connect "localhost" 8080) + ((exn i/o net) (lp)))) + (close-output-port out) + (close-input-port in) + (check (tcp-addresses in)) + (check (tcp-port-numbers in)) + (check (tcp-abandon-port in))) ; Not sure about abandon-port + +(print "\n\nProcedures check on output ports being closed\n") + +(call-with-output-file "/dev/null" + (lambda (out) + (close-output-port out) + (check (write '(foo) out)) + (check (fprintf out "blabla")) + (check "print-call-chain" (begin (print-call-chain out) (void))) + (check (print-error-message (make-property-condition 'exn 'message "foo") out)) + (check "print" (with-output-to-port out + (lambda () (print "foo")))) + (check "print*" (with-output-to-port out + (lambda () (print* "foo")))) + (check (display "foo" out)) + (check (terminal-port? out)) ; Calls isatty() on C_SCHEME_FALSE? + (check (newline out)) + (check (write-char #\x out)) + (check (write-line "foo" out)) + (check (write-u8vector '#u8(1 2 3) out)) + (check (port->fileno out)) + (check (flush-output out)) + (check (file-test-lock out)) + (check (file-lock out)) + (check (file-lock/blocking out)) + (check (write-byte 120 out)) + (check (write-string "foo" #f out)))) + +(print "\n\nProcedures check on input ports being closed\n") +(call-with-input-file "/dev/zero" + (lambda (in) + (close-input-port in) + (check (read in)) + (check (read-char in)) + (check (char-ready? in)) + (check (peek-char in)) + (check (port->fileno in)) + (check (terminal-port? in)) ; Calls isatty() on C_SCHEME_FALSE? + (check (read-line in 5)) + (check (read-u8vector 5 in)) + (check "read-u8vector!" (let ((dest (make-u8vector 5))) + (read-u8vector! 5 dest in))) + (check (file-test-lock in)) + (check (file-lock in)) + (check (file-lock/blocking in)) + (check (read-byte in)) + (check (read-token (constantly #t) in)) + (check (read-string 10 in)) + (check "read-string!" (let ((buf (make-string 10))) + (read-string! 10 buf in) buf)))) \ No newline at end of fileTrap