[flexi-streams-devel] Re: note on flexi-streams
rpgoldman at real-time.com
rpgoldman at real-time.com
Tue Jun 13 15:05:25 UTC 2006
>>>>> "EW" == Edi Weitz <edi at agharta.de> writes:
[...snip...]
EW> On Thu, 1 Jun 2006 14:35:26 -0500, "Robert P. Goldman"
EW> <rpgoldman at sift.info> wrote:
>> I just pulled a copy of flexi-streams, using asdf-install, and
>> had a couple of minor problems:
>>
[...snip...]
>> 2. Making a flexible stream with an external format blows up
>> for me
>> on ACL. E.g., cl-irc tries to make a flexi-io-stream with
>> external format (:utf-8 :eof-type :crlf)
>>
>> This value is stuffed into the flexi-stream slot
>> EXTERNAL-FORMAT. Unfortunately, IIUC, this also triggers an
>> Allegro-specific method as follows:
>>
>> (METHOD (SETF STREAM-EXTERNAL-FORMAT) :BEFORE (T STREAM))
>>
>> This method checks to make sure that the value you are setting
>> as a stream-external-format is an excl:external-format object.
>> In this case, it clearly isn't, so the :before method hurls an
>> error.
>>
>> I believe that this error is triggered because a
>> flexi-io-stream ISA fundamental-binary-input-stream which ISA
>> stream.
>>
>> I confess I'm not really sure what to do about this problem....
EW> Hmm, at first glance I'd say that this is either an AllegroCL
EW> bug or it is not related to FLEXI-STREAMS at all. The slot
EW> you're talking about above is called
EW> FLEXI-STREAMS::EXTERNAL-FORMAT, its name is not exported from
EW> the package. I can't see why setting the value of this slot
EW> should trigger an Allegro-specific method.
EW> (Note that on AllegroCL EXCL:EXTERNAL-FORMAT is accessible in
EW> various packages, including CL-USER. Maybe you're seeing a
EW> package conflict?)
The problem is not the FLEXI-STREAMS::EXTERNAL-FORMAT symbol, but the
use of :external-format as an initarg, IIUC. See the (relatively)
simple test case below for more details.
EW> It'd be nice if you could provide a simple test case which
EW> provokes this error message, so we can see what's really going
EW> on.
OK. Understand that I don't really know how flexi-streams are
supposed to work --- I just stumbled into this because I use BEIRC,
which uses CL-IRC, which (newly) uses FLEXI-STREAMS. So I'm pretty
far from understanding things, and some of the things that I give may
not be bugs; they may be me using the package wrong.
My first shot at causing an error is the following:
(defpackage :flexi-test (:use :common-lisp :flex))
(in-package :flexi-test)
(setf foo (open "/tmp/foo" :direction :io))
(setf bar (make-flexi-stream foo))
Error: :DEFAULT is not known to be a name for an external format.
Restart actions (select using :continue):
0: Return to Top Level (an "abort" restart).
1: Abort entirely from this (lisp) process.
[1] FLEXI-TEST(18): :bt
Evaluation stack:
FLEX::NORMALIZE-EXTERNAL-FORMAT-NAME <-
FLEX::MAKE-EXTERNAL-FORMAT% <- MAKE-EXTERNAL-FORMAT <-
FLEX::MAYBE-CONVERT-EXTERNAL-FORMAT <-
(METHOD INITIALIZE-INSTANCE :AFTER ...) <-
(:INTERNAL (:EFFECTIVE-METHOD 1 T ...) 0) <-
(METHOD MAKE-INSTANCE (CLASS)) <- (METHOD MAKE-INSTANCE (SYMBOL)) <-
MAKE-FLEXI-STREAM <- [... EXCL::%EVAL ] <- LET* <- [... EXCL::%EVAL ] <-
EVAL <- TPL:TOP-LEVEL-READ-EVAL-PRINT-LOOP <- TPL:START-INTERACTIVE-TOP-LEVEL
[I'm honestly not sure where the :default value comes from, and it may
be that I am simply committing an error here and that the
:external-format keyword is mandatory, rather than optional, as I have
treated it.]
So I tried to do what cl-irc does:
(defun external-format-fixup (format)
(let ((new-format (copy-list format)))
(setf (getf (cdr new-format) :eol-style) :crlf)
new-format))
(defun mock-connect (&key (server "irc.freenode.net")
(port 6667)
(connection-type 'connection)
(logging-stream t))
(let* ((stream (socket-connect server port))
(connection (make-connection :connection-type connection-type
:network-stream stream
:client-stream logging-stream
:server-name server)))
(values connection stream)))
(defun make-connection (&key (connection-type 'connection)
(user nil)
(password nil)
(server-name "")
(server-port nil)
(network-stream nil)
(outgoing-external-format *default-outgoing-external-format*)
(client-stream t)
(hooks nil))
(let ((output-stream (flexi-streams:make-flexi-stream
network-stream
:element-type 'character
:external-format (external-format-fixup outgoing-external-format))))
output-stream))
;; overlooked this dependency....
(asdf:oos 'asdf:load-op :trivial-sockets)
(defun socket-connect (server port)
"Create a socket connected to `server':`port' and return stream for it."
(trivial-sockets:open-stream server port :element-type '(unsigned-byte 8)))
(setf *default-outgoing-external-format* '(:utf8))
That gets me the error:
FLEXI-TEST(62): (mock-connect)
Error: `:EOL-STYLE' does not name an external-format.
[condition type: NO-EXTERNAL-FORMAT-ERROR]
Restart actions (select using :continue):
0: Return to Top Level (an "abort" restart).
1: Abort entirely from this (lisp) process.
[1] FLEXI-TEST(63): :bt
Evaluation stack:
(METHOD (SETF STREAM-EXTERNAL-FORMAT) :BEFORE ...) <-
(:INTERNAL (:EFFECTIVE-METHOD 2 NIL ...) 0) <-
(:INTERNAL (:EFFECTIVE-METHOD 2 T ...) 0) <-
(METHOD INITIALIZE-INSTANCE (STANDARD-OBJECT)) <-
(:INTERNAL (:EFFECTIVE-METHOD 1 T ...) 0) <-
(METHOD MAKE-INSTANCE (CLASS)) <- (METHOD MAKE-INSTANCE (SYMBOL)) <-
MAKE-FLEXI-STREAM <- LET <- MAKE-CONNECTION <- LET* <- MOCK-CONNECT <-
EVAL <- TPL:TOP-LEVEL-READ-EVAL-PRINT-LOOP <- TPL:START-INTERACTIVE-TOP-LEVEL
The error happens when making the flexi-io-stream class. It triggers
this ACL :before method that checks the value of the
stream-external-format, and which seems to be seeing the
'(:utf8 :eol-style :crlf) value that cl-irc is stuffing into the
flexi-stream constructor.
ACL has a method that evidently checks the assignment to
stream-external-format for every stream to make sure that it is a
legitimate excl-external-format, IIUC. A flexi-stream ISA stream, so
somehow this is triggered. Your email seems to suggest that you did
NOT expect the flexi-stream-value to become the
stream-external-format, right? But this is the make-instance call:
((METHOD MAKE-INSTANCE (CLASS)) #<STANDARD-CLASS FLEXI-IO-STREAM> :STREAM
#<MULTIVALENT stream socket connected from 192.168.1.18/41332 to
kornbluth.freenode.net/6667 @ #x71dc7412>
:ELEMENT-TYPE CHARACTER :EXTERNAL-FORMAT (:UTF8 :EOL-STYLE :CRLF))
So even though flexi-streams::external-format is not exported,
flexi-streams is using the :external-format keyword in its
make-instance call, and that is triggering the ACL code. Would it be
enough to fix things to change the :initarg to
":flexi-stream-external-format"? That seems cumbersome, though. I
don't know another way to keep ACL from grabbing up the
:external-format keyword arg, though... But again, I have not thought
deeply about this.
More information about the Flexi-streams-devel
mailing list