[gambit-list] Input buffering and other IO issues

Christian christian at pflanze.mine.nu
Sun Jan 8 02:45:00 EST 2006


Hello

I wanted to write a small program which reads exactly n bytes from a
port (and calculates an md5 hash on them, like "head -c n | md5sum").

It turned out that even with buffering: #f, read-subu8vector reads
through buffers, as strace shows (it reads in 1024 byte chunks, not in
the lengths I'm giving to read-subu8vector).

The reason why I want it to not read past the given number of bytes
is:
- I wanted to checksum a cdrom (by reading from /dev/cdrom), and
reading past the length of the cdrom image is giving read errors on my
OS (linux on ppc).
- I might need it for reading from pipes and not block (I've not
checked whether gambit would block the thread or not), or worse, read
from pipes used for interprocess-locking (even if gambit doesn't block
when trying too many bytes from a pipe, it will break the idea of
using pipes for locking).


(define-macro (qq . lis)
  (list 'quasiquote lis))

(define (test bytes path)
  (call-with-input-file (qq path: ,path
			    ;;char-encoding: #f  -> STRING or port settings expected
			    char-encoding: ascii
			    buffering: #f
			    )
    (lambda (port)
      (let ((buf (make-u8vector bytes)))
	(let ((res (read-subu8vector buf 0 bytes port)))
	  res)))))

> (test 20 "./cj-md5sum-cdrom.scm" )
20

open("/home/chris/schemedevelopment/gambit/mod/./cj-md5sum-cdrom.scm", O_RDONLY|O_NONBLOCK) = 4
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbf911cc8) = -1 ENOTTY (Inappropriate ioctl for device)
fstat64(4, {st_mode=S_IFREG|0664, st_size=2258, ...}) = 0
read(4, "; cj Sun, 08 Jan 2006 01:29:03 +"..., 1024) = 1024
close(4)                                = 0
write(3, "2", 1)                        = 1
write(3, "0", 1)                        = 1
write(3, "\n", 1)                       = 1
write(3, ">", 1)                        = 1
write(3, " ", 1)                        = 1


In this strace output a second issue can be seen as well: output to
the console is done in single bytes (maybe chars). This makes output
of a gambit process to emacs (when running under run-scheme) slow
(much so on my laptop, where there seems to be an issue with frequent
system calls between programs). Either outputting objects as a whole
instead of single characters (the way unbuffered output in e.g. perl
works), or buffering on line boundaries, would be an improvement.


Finally, I can't understand why I'm getting this:

> (test 10 "/dev/cdrom")        
*** ERROR IN (console)@7.1 -- Unknown error
(call-with-input-file '(path: "/dev/cdrom" char-encoding: ascii buffering: #f) '#<procedure #3>)
1> 

head -c 10 /dev/cdrom works just fine, as the same system user. It
might help if the error message would include the OS level message.

strace output:
open("/dev/cdrom", O_RDONLY|O_NONBLOCK) = 4
ioctl(4, TCGETS, 0x7ffff148)            = -1 EINVAL (Invalid argument)
fstat(4, {st_mode=S_IFBLK|0660, st_rdev=makedev(22, 0), ...}) = 0
close(4)                                = 0

Thanks
Christian.




More information about the Gambit-list mailing list