[Openmcl-devel] duplicating a stream
Gary Byers
gb at clozure.com
Mon Mar 26 16:12:00 PDT 2012
See below.
On Mon, 26 Mar 2012, Pascal J. Bourguignon wrote:
>
> When calling run-program, one need to pass a :shared stream.
>
> Since I may get non shared file streams (by default they're :private),
> I'd want to "duplicate" the stream, making a shared stream to give to
> run-program, using the same stream-device:
>
> (defun wrap-stream (direction stream)
> ;; Since stream may not be shared, we make a new stream for
> ;; the process.
> (typecase stream
> (stream (ccl::make-basic-stream-instance
> (if (eql :input direction)
> 'file-character-input-stream
> 'file-character-output-stream)
> :stream-device (ccl::stream-device stream direction)
> :direction direction
> :element-type 'character
> :sharing :lock
> :encoding ccl:*default-file-character-encoding*
> :line-termination #+windows :windows #-windows :unix
> :auto-close t))
> (otherwise stream)))
>
> Unfortunately that fails with:
>
> There is no applicable method for the generic function:
> #<standard-generic-function ccl:class-own-wrapper #x302000032F0F>
> when called with arguments:
> (com.informatimago.run-program::file-character-output-stream)
> [Condition of type simple-error]
>
> What did I do wrong?
>
1) called some random internal CCL function.
1a) called that function with the wrong type of arguments (the first
arg is expected to be a CLASS object, not a symbol that names a class)
1b) called that function with symbols that don't even name classes (though
symbols with the same pnames that're internal to the CCL package do
happen to name classes).
UPDATE: you get some points back for noticing this, but I'm afraid that
that barely matters.
2) decided that this should happen if your function's argument is of type STREAM.
(STRING-STREAMs and lots of other things are of type STREAM.)
3) Think that creating a situation where two lisp streams share the same file
descriptor would be a good idea. (There might be cases where this is useful,
but as a general rule I think it's fair to say that this isn't a good idea.)
4) In CCL (and most other programming languages), streams are often buffered;
the "state" (position, set of characters/bytes read/written, etc.) of the
stream and that of the underlying file descriptor are related to each other
but aren't generally identical. If it made sense to "duplicate a stream",
creating another stream that uses the same fd would only be a small part
of that.
5) That's enough for now.
Until an hour or two ago, the documentation said that a stream created with
:SHARING :PRIVATE could only be used by the thread that created it. That
hasn't been true in several years: such a stream is "owned" by whatever
thread first tries to do I/O on the stream, so common idioms like:
(with-open-file (f path)
(process-run-function "something" (lamba () (print (read-line f))))
(sleep long-enough-to-let-the-thread-run))
work as expected. (I don't claim that that's a plausible-looking example,
but I think that the idiom's indeed fairly common.)
The case that I can think of where this (stream sharing/ownership) matters
involves things like:
(with-open-file (f "home:log.txt" :sharing :private :direction :output :if-does-not-exist :create :if-exists :superseded)
(write-line "Copyright (c) 2012 Acme Corporation." f) ; become stream's "owner"
(run-program "/bin/echo" '("yow!") :output f))
(I think that some versions of a widely-used CL logging package run into this or
something similar.) If this can't be made to work, it'd probably be better
to complain about the argument earlier; in this particular case - where the stream
is essentially thread-private except for the fact that a thread used in the
implementation of RUN-PROGRAM wants to write to it) there may be ways to avoid
the error (possibly by temporarily transferring ownership of the stream to
the background process.)
>
> --
> __Pascal Bourguignon__ http://www.informatimago.com/
> A bad day in () is better than a good day in {}.
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
>
More information about the Openmcl-devel
mailing list