[Openmcl-devel] string-output-stream thread unsafety with hunchentoot (ccl, darwin/x86-64)
Gary Byers
gb at clozure.com
Wed Apr 15 00:15:32 PDT 2009
On Mon, 13 Apr 2009, Gail Zacharias wrote:
> On Thu, Apr 9, 2009 at 1:55 PM, Gary Byers <gb at clozure.com> wrote:
>> The assumptions in question are that:
>> - string-output-streams are thread-private
>
> Would it slow them down too much to check for this, like
> thread-private file streams do? I might be seeing a case of this
> (string output streams being passed across threads) and it would help
> to get an error right when it first happens.
>
It shouldn't be too bad to do that check, and enforcing thread-privacy
might also guard against other kinds of lossage.
The only downside that I can think of is that doing this - making
string-output-streams enforce their thread-privateness - might make
it difficult to create some sort of intentionally shared encapsulating
class (unless some way of clearing the owner info.) I'm not sure
that that's much of a loss, and the whole notion of intentionally
passing string-output-streams around between threads seems kind of
ill-advised ...
In any case, I think that the changes in the enclosed patch are
all that'd be needed to enforce thread-privateness and they seem
to work; I'm a little hesitant to commit those changes without
testing it more than I have, but I -think- it's fair to say that the
cost of checking is pretty small.
-------------- next part --------------
Index: level-1/l1-streams.lisp
===================================================================
--- level-1/l1-streams.lisp (revision 11875)
+++ level-1/l1-streams.lisp (working copy)
@@ -4237,6 +4237,7 @@
;;; Should only be used for a stream whose class is exactly
;;; *string-output-stream-class*
(defun %close-string-output-stream (stream ioblock)
+ (check-ioblock-owner ioblock)
(when (eq (basic-stream.wrapper stream)
*string-output-stream-class-wrapper*)
(without-interrupts
@@ -4258,7 +4259,7 @@
(ioblock-charpos data) 0
(string-output-stream-ioblock-index data) 0))
data)))))
- (or recycled (apply #'make-string-output-stream-ioblock keys))))
+ (or recycled (apply #'make-string-output-stream-ioblock :owner *current-process* keys))))
@@ -4329,6 +4330,7 @@
(%%make-string-output-stream *fill-pointer-string-output-stream-class* string 'fill-pointer-string-output-stream-ioblock-write-char 'fill-pointer-string-output-stream-ioblock-write-simple-string))
(defun string-output-stream-ioblock-write-char (ioblock char)
+ (check-ioblock-owner ioblock)
(let* ((string (string-output-stream-ioblock-string ioblock))
(index (string-output-stream-ioblock-index ioblock))
(len (length string)))
@@ -4350,6 +4352,7 @@
(declare (simple-string string)
(fixnum start-char num-chars)
(optimize (speed 3) (safety 0)))
+ (check-ioblock-owner ioblock)
(let* ((out (string-output-stream-ioblock-string ioblock))
(index (string-output-stream-ioblock-index ioblock))
(len (length out))
@@ -4383,6 +4386,7 @@
(defmethod stream-position ((stream string-output-stream) &optional newpos)
(let* ((ioblock (basic-stream-ioblock stream)))
+ (check-ioblock-owner ioblock)
(if (null newpos)
(string-output-stream-ioblock-index ioblock)
(if (and (typep newpos 'fixnum)
More information about the Openmcl-devel
mailing list