Helmut Eller <firstname.lastname@example.org> wrote:
| email@example.com (Christopher C. Stacy) writes:
| > Which Lisp programs are you reporting on,
| > that you had all these bugs?
| Here's an example:
| This is SBCL's reader. The code is almost portable CL. And it has a
| threading bug. Can you spot it? The problem is the global
| *read-buffer*, a string that's used to implement various stuff
| efficiently. But there's no code at all to synchronize concurrent
| access/modifications to the buffer. If two unrelated threads call
| READ at the same time, they will use the same buffer and can possibly
| interfere with each other.
Interesting. The corresponding CMUCL file contains this macro:
;;; Recursive reader functions use with-read-buffer to allocate a
;;; fresh buffer. We currently allocate a fresh buffer only for the
;;; exported functions READ, READ-PRESERVING-WHITESPACE,
;;; READ-FROM-STRING, and READ-DELIMITED-LIST. Some internal
;;; functions like READ-TOKEN, INTERNAL-READ-EXTENDED-TOKEN and
;;; READ-STRING avoid the overhead for the allocation and clobber the
;;; current read-buffer.
(defmacro with-read-buffer (() &body body)
"Bind *read-buffer* to a fresh buffer and execute Body."
`(let* ((*read-buffer* (allocate-read-buffer))
(*read-buffer-length* (length *read-buffer*))
(unwind-protect (progn ,@body)
Note that CMUCL's [and one would hope, SBCL's] MP package keeps bound
specials per-thread, thus the LET* means that each thread gets their own
private *READ-BUFFER*, *READ-BUFFER-LENGTH*, *OUCH-PTR*, & *INCH-PTR*.
Rob Warnock <firstname.lastname@example.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607