Opened 4 years ago

Last modified 4 years ago

#1716 new defect

coops + s11n malfunction

Reported by: Idiomdrottning Owned by:
Priority: major Milestone: someday
Component: extensions Version: 5.1.0
Keywords: coops s11n Cc:
Estimated difficulty:

Description

(define-class frotz () ((name accessor: name)))
(define xyzzy (make frotz 'name "blue jeans"))
(name xyzzy)
(with-output-to-file "/tmp/frotz" (lambda () (serialize xyzzy)))
(define nitfol (with-input-from-file "/tmp/frotz" deserialize))
nitfol ; <= evals to  #<coops instance of `frotz'>
(name nitfol); <= fails with Error: (name) no method defined for given argument classes: (#<coops instance of `<standard-class>'>)

This used to work and print "blue jeans" but I'm not sure when it stopped working. I especially hope I can rescue all my other saved objects because I have a lot of precious in there♥

Change History (2)

comment:1 Changed 4 years ago by Idiomdrottning

OK I've since gone back and checked and what used to work was defstruct, not coops. So this has never been proved to work. It's still a bug, and an interesting one—"nitfol" seems to be a frotz at first but then isn't.

comment:2 Changed 4 years ago by Idiomdrottning

OK, so the following works in interpreted code and in compiled code up
to -O4 after deserialization:

(define (coops-restore! x)

(##sys#setslot x 1 (eval (class-name (class-of x)))))

After (coops-restore! nitfol) it behaves just like any other frotz,
and (name nitfol) returns "blue jeans".

(If frotz is defined in the continuation ofc.)

This isn't recursive so any other instances or class inside of the
deserialized object, including in lists, vectors, hashtables etc would
also have to be restored.

So the problem with the coops/s11n is with coops' fundamental design.
<standard-class> is defined as a recursive structure. The standard
class is also an instance of standard class. But, testing to see
whether something is the standard class tests for eq with
<standard-class> in the environment. That's an eq-relationship that
breaks on deserialization.

Deserialization can handle recursive structures (like circular lists)
just fine. The S11N egg uses a ref table. But it can't check for eq
with structs in the environment. It can handle symbols (somehow…) but
not just (eq? a b) where both a and b are names for the same
coops#coops-instance.

My idea for a workaround was to try to walk the deserialized
coops-instances and replace any references to the fake
<standard-class> (which still has the class name <standard-class>,
just not environment eq-equality) with the real one. But, all these
nonsense recursive structures is making that very difficult.

(The nonsense recursive structures being created by deserializing
<standard-class>)

The issue here is with using continuation eq-equality (to a completely
cockamamie recursive struct that it itself relies on the
aforementioned eq-equality) instead of a symbol in slot 0 like any
other datum.

The two solutions I can see is to either make s11n handle coops object
specially, by storing a <standard-class> as just a tag (tag number 21
perhaps) instead of as a recursive structure and then restoring it
from the environment. Or, ideally, by reworking coops so that
<standard-class> is based on having a specific symbol rather than a
specific eq-relationship with a structure defined or exported to the
continution.

Note: See TracTickets for help on using tickets.