[M3devel] Question about TEXTs under CM3

Tony Hosking hosking at cs.purdue.edu
Thu Jul 26 15:47:46 CEST 2007


Looks like we need to fix M3toC.StoT so that it works the same as old  
PM3.  The old code works because it constructs a text *in* the heap  
as an ARRAY OF CHAR, that just happens to have its payload (the array  
contents) outside the heap.  (Arrays in M3 contain a reference to  
their data).  We can play the same trick for Text8CString and get  
things to work properly for you.  I will make this fix and check it in.


On Jul 26, 2007, at 8:40 AM, Mika Nystrom wrote:

> Ok, I am about to answer my own email.  Here's a little program I  
> wrote:
>
> MODULE Main;
> IMPORT Pickle, IO, Params, TextWr, TextRd;
>
> VAR wr := NEW(TextWr.T).init();
>     toPickle := "pickle this";
> BEGIN
>   IF Params.Count > 1 THEN toPickle := Params.Get(1) END;
>
>   Pickle.Write(wr,toPickle);
>
>   IO.Put("pickled \""&toPickle&"\"\n");
>   IO.Put("read back \""&
>          Pickle.Read(NEW(TextRd.T).init(TextWr.ToText(wr)))
>          &"\"\n");
> END Main.
>
> === On FreeBSD4 with my ancient, creaky PM3:
>
> (64)trs80:~/ptest/src>../FreeBSD4/pickleit
> pickled "pickle this"
> read back "pickle this"
> (65)trs80:~/ptest/src>../FreeBSD4/pickleit pickle\ that
> pickled "pickle that"
> read back "pickle that"
>
> === On PPC_DARWIN with the latest CM3:
>
> [QT:~/ptest/src] mika% ../PPC_DARWIN/pickleit
> pickled "pickle this"
> read back "pickle this"
> [QT:~/ptest/src] mika% ../PPC_DARWIN/pickleit pickle\ that
> pickled "pickle that"
>
>
> ***
> *** runtime error:
> ***    Segmentation violation - possible attempt to dereference NIL
> ***
>
> Abort
>
> === On FreeBSD4 with the latest CM3:
>
> (73)rover:~/ptest/src>../FreeBSD4/pickleit
> pickled "pickle this"
> read back "pickle this"
> (74)rover:~/ptest/src>../FreeBSD4/pickleit pickle\ that
> pickled "pickle that"
>
>
> ***
> *** runtime error:
> ***    Segmentation violation - possible attempt to dereference NIL
> ***
>
> Abort
>
> ============
>
> Diagnosis:
>
> The code I mentioned in a previous email declares a Text8CString.T
> to be of type TEXT OBJECT str: Ctypes.char_star; END .  Elsewhere
> in the system, Ctypes.char_star is specifically declared to be an
> "UNTRACED REF Ctypes.char".  According to the specification of
> Pickle, an UNTRACED REF is pickled as NIL.
>
> Generally speaking, you don't see many Text8CString.Ts in the system.
> This one comes in via Params.Get, which in turn calls RTArgs.GetArg,
> which in turn calls M3toC.StoT.
>
> StoT is generally not something you want to call, but it's supposed
> to be OK here because you're just passing around argv, which won't
> change.  Generally speaking, it ought to be OK to use to convert
> C strings whose addresses aren't going to change during the lifetime
> of the program.
>
> I think it is *totally unacceptable* that Params.Get returns a
> "poisoned" TEXT.  There is absolutely nothing in any of the interfaces
> that warns of this fact, and it is surprising to say the least.
> There is also no simple way of "copying" TEXTs, as it shouldn't
> ever be required!  Finally, there's no way of checking whether a
> TEXT is a Text8CString.T without importing Text8CString, which is
> an UNSAFE INTERFACE, which of course is illegal in a safe MODULE!!
>
> What does baffle me a bit is that the code works on the old PM3.
> It uses the old TextF, which declares
>
>   TEXT = BRANDED Text.Brand REF ARRAY OF CHAR;
>
> The old (from PM3, I think it's 1.1.15) M3toC has:
>
> PROCEDURE StoT (s: Ctypes.char_star): TEXT =
>   VAR t := NEW (M3TextWithHeader);
>   BEGIN
>     t.header.typecode := RT0.TextTypecode;
>     t.body.chars      := LOOPHOLE (s, ADDRESS);
>     t.body.length     := 1 + Cstring.strlen (s);
>     RETURN LOOPHOLE (ADR (t.body), TEXT);
>   END StoT;
>
> I'm not entirely sure why the old code works---why isn't the
> M3TextWithHeader garbage-collected?   The pickler doesn't seem to
> know that the result of LOOPHOLE (ADR (t.body), TEXT) is special.
> In fact the pickler doesn't seem to know anything about TEXTs
> at all.
>
> I see several possible ways of solving the problem.  One is to
> permit M3toC.StoT to remain broken (since M3toC is an UNSAFE
> interface, there's no "legal" reason not to do that) and make sure
> Params.Get (and everything else that could remotely be called
> "standard") doesn't use M3toC.StoT---oh and to leave some very
> prominent warning signs, both in M3toC and Text8CString that "here
> be demons".  Another is to revert to the SRC method of LOOPHOLEing
> the C strings.  I never liked the CM3 TEXTs, and I like them even
> less now; I disliked them from the start because they broke pickle
> compatibility with SRC M3, and now I find that they aren't even
> compatible with themselves.
>
> Modula-3's strengths have always been its utter simplicity
> and bullet-proof reliability.  This stuff, where some objects are
> more "serializable" than others, reminds me of Java!
>
> Does anyone have an opinion as to how this problem ought to be
> solved?
>
>      Mika
>
> Mika Nystrom writes:
>> Hello everyone,
>>
>> Here's a random question that hopefully someone can answer...
>>
>> Is it true that certain TEXTs can't be Pickled under CM3?
>>
>> Unless there's some magic I don't understand going on, I am thinking
>> that would be the implication of:
>>
>> UNSAFE INTERFACE Text8CString;
>> ...
>> TYPE
>>  T <: Public;
>>  Public = TEXT OBJECT
>>    str: Ctypes.char_star;
>>  END;
>>  (* The array contains the characters of the text followed by a  
>> '\000'. *)
>> ...
>>
>> I hope someone can set me straight and tell me that no, the situation
>> isn't as dire as that---some clever thing somewhere makes it possible
>> to Pickle all objects of type TEXT...
>>
>>     Mika




More information about the M3devel mailing list