Two classes with same name -- unpleasantly odd bug

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Two classes with same name -- unpleasantly odd bug

Chris Uppal-3
Hi,

I'm starting a new thread, but it is really a continuation under a different
name of Bill's thread, '#browseDefinitionsOf: includes redundant item - time to
panic?', from a couple of weeks back.

Ian, Bill, and I, have all seen a situation where you can end up with two
classes with the same name.  That's to say that the Smalltalk dictionary
includes only one of them, but the subclasses list(s) of their parent class
(and metaclass's parent) includes two Class objects with the same name.

I've tried to reproduce it, and had found what seemed to be a nice reproducible
test case.  However, stepping through the code did /not/ show the bug.  And --
worse -- as I was writing up a post describing it, it stopped "working"
altogether (the bug vanished) and I can't reproduce it at all now (so some of
the description below is from memory, unfortunately).

Basically, the problem is that evaluating an expression that removes instvars,
and thus leaves some methods with syntax errors, can result in two versions of
the class existing at once.

It has shown up for all of us when using the Chunk Browser, but it isn't the
CB's fault.  It can be reproduced just by evaluating class creation expressions
in a workspace.  As far as I could tell, it /had/ to be evaluated like that (or
in the environment that the CB sets up) for the bug to manifest.  Oddly (but
perhaps coincidentally) I couldn't get it to fail when just filing-in the
equivalent expression.

Anyway, to (try to) reproduce:

Work in a throwaway image!

Create a class AAATemp.

Create a fileout of that class, AAATemp.cls (you may as well edit it to remove
the GUID declaration, etc, since only the class creation expression will be
needed).

Add an instvar, 'var' to that class, and a method that accesses it:
    aMethod
        ^ var.

Save your image at this point, everything we do hereafter
is awkward to reverse and what we've done is tedious to recreate.

Now evaluate the following in a workspace:

 Object
    subclass: #AAATemp
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''
    classInstanceVariableNames: ''

(which is just a normal class definition expression, of course) and open a new
CHB.  If the demo has "worked" there should now be two classes called AAATemp
(you do have to open a new CHB, any existing ones don't update).

Exit that image without saving, and restart (thus backing up to just before the
point where we evaluated the expression).  This time try filing in
'AAATemp.cls' which will evaluate a class-creation method just like the above.
If your experience is the same as mine, then this will work correctly.

Can anyone re-create this ?

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Two classes with same name -- unpleasantly odd bug

Yar Hwee Boon-3
On Thu, 16 Dec 2004 10:28:47 -0000, Chris Uppal  
<[hidden email]> wrote:

> Can anyone re-create this ?

I can't, on a 5.1.4 fresh image. In both cases, I only see 1 AAATemp class  
in the new CHB, which no "var" defined.

--
Regards
HweeBoon
MotionObj


Reply | Threaded
Open this post in threaded view
|

Re: Two classes with same name -- unpleasantly odd bug

Ian Bartholomew-19
In reply to this post by Chris Uppal-3
Chris,

The following works reliably - is it connected to your example?

Create a class AAATemp with one instVar (as in your example).  Then, in a
workspace, evaluate (either together or one statement at a time) ...

Smalltalk at: #AAATemp put: nil.
Object subclass: #AAATemp
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''
    classInstanceVariableNames: ''

Opening up a CB shows two AAATemp classes, one with an instVar and one
without.  It raises a couple of questions about globals that aren't classes

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: Two classes with same name -- unpleasantly odd bug

Ian Bartholomew-19
I wrote...

> without.  It raises a couple of questions about globals that aren't
> classes

No it doesn't :-). A class (Object in this case) caches it's subclasses and
removing #AAATemp from the SystemDictionary in this way doesn't remove it
from #Object's cache.  As the original class object still has hard
references, from #Objects classes instVar, it is not garbage collected and
remains available - albeit not from the SystemDictionary.  #Object's classes
instVar now contains two valid #AAATemp objects so when the ClassBrowser is
opened both are displayed.

Motto - Don't nil out classes in the SystemDictionary, use #removeFromSystem
instead.

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.
"


Reply | Threaded
Open this post in threaded view
|

Re: Two classes with same name -- unpleasantly odd bug

Schwab,Wilhelm K
Ian,

> Motto - Don't nil out classes in the SystemDictionary, use #removeFromSystem
> instead.

Dumb question: does this affect only your example, or does it perhaps
get to the bottom of the problem?  Could you, Chris, and I be falling
into the same trap?  Indirectly?

In addition to your CB, I spend a fair amount of time running my code
generator and friends.

Chris, we hinted slightly at the possibility of a tool that would
detect, and maybe even be able to undo the "damage".  Is that something
we could/should try to build?  If it can tell which is the redundant
class, perhaps it could file out all of its methods prior to removing
it; otherwise, it could file out everything and offer expressions to
help the user remove one of the other class.

If we are reasonably certain the CB is indeed innocent in this, perhaps
it could be used to simplify browsing the suspect methods.

Have a good one,

Bill


--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Two classes with same name -- unpleasantly odd bug

Chris Uppal-3
In reply to this post by Yar Hwee Boon-3
Yar Hwee Boon wrote:

> > Can anyone re-create this ?
>
> I can't, on a 5.1.4 fresh image. In both cases, I only see 1 AAATemp class
> in the new CHB, which no "var" defined.

Thank you for trying.

This is definitely an odd one...

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Two classes with same name -- unpleasantly odd bug

Chris Uppal-3
In reply to this post by Schwab,Wilhelm K
Bill,

> > Motto - Don't nil out classes in the SystemDictionary, use
> > #removeFromSystem instead.
>
> Dumb question: does this affect only your example, or does it perhaps
> get to the bottom of the problem?  Could you, Chris, and I be falling
> into the same trap?  Indirectly?

I don't believe so.

My workspace expression doesn't go anywhere near the system dict (except
insofar as the class builder does it, but that's where the bug must lie -- in
some sense).


> Chris, we hinted slightly at the possibility of a tool that would
> detect, and maybe even be able to undo the "damage".  Is that something
> we could/should try to build?

A workspace expression to detect such occurrences is easy enough.

    classes := Class allSubinstances.
    names := (classes collect: [:each | each name]) asBag.
    odd := classes select: [:each | (names occurrencesOf: each name) > 1]


A few workspace expressions to fix-up the damage could be worked out too, based
on Class>>removeFromSuper and Class>>fileOutOn:.  (Remembering to check that
the duplicate classes had duplicate metaclasses before fixing the metaclasses)

The problem (which would be especially severe for a proper tool) is how to test
it ?  I wouldn't be happy using a tool that grubbed around in the bowels of my
image[*] unless I knew it had received /lots/ of testing.  But how do we test
it when we can't reproduce the bug ?   And if we /could/ reproduce the bug,
then I'm sure OA would fix it easily enough.  Still, there is /some/ good
news -- I've just managed to reproduce it again in the throwaway image I was
using for testing, so there's hope of pinning it down yet.  I don't have time
to do anything more today, but I'll investigate more later.

([*] it could be that the phrase "grubbed around in the bowels of my image" has
never been used before by mortal man ;-)  Google doesn't find any match, but it
does ask if I'm "Looking for pictures?" -- thanks, but no!)


> If we are reasonably certain the CB is indeed innocent in this,

I really can't think of any way that the CB could be implicated.  I currently
/suspect/ that its an innocent victim of some semi-deterministic interaction
between the environment where an expression is evaluated and the handlers for
the various kinds of compilation Exception.  But that's just a suspicion.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Two classes with same name -- unpleasantly odd bug

Ian Bartholomew-19
In reply to this post by Schwab,Wilhelm K
Bill,

> Dumb question: does this affect only your example, or does it perhaps get
> to the bottom of the problem?  Could you, Chris, and I be falling into the
> same trap?  Indirectly?

Probably not, but I think it /might/ help narrow down where any problem
/may/ occur.

I spent a bit of time going though the what happens to the #subclasses
collection in a classes superclass when you modify the classes definition.
A precis ....

A new modified subclass is created.
The new class is added to its superclasses #subclasses collection (which now
contains two different versions of the same subclass).
*A lot goes on - including recompiling all the methods in the class.
The old class is removed from the superclasses #subclasses collection.

If something untoward should happen in the line with the asterisk, causing
an abort in the process, then it is /possible/ that we could end up with a
superclass that a browser shows as having two classes with the same name.

As to what could cause the abort.... <shrug>

--
Ian

Use the Reply-To address to contact me.
Mail sent to the From address is ignored.


Reply | Threaded
Open this post in threaded view
|

Re: Two classes with same name -- unpleasantly odd bug

Chris Uppal-3
Ian, Bill,

> I spent a bit of time going though the what happens to the #subclasses
> collection in a classes superclass when you modify the classes definition.
> A precis ....
>
> A new modified subclass is created.
> The new class is added to its superclasses #subclasses collection (which
> now contains two different versions of the same subclass).
> *A lot goes on - including recompiling all the methods in the class.

I've found that my original example exhibits the bug reliably when I load the
.cls file via the chunk browser.

The problem seems to be that ChunkBrowserExpressionChunk>>restoreAndLog:
consumes the error notification, thus aborting the intermediate processing.
Adding
    e pass
to the handler block seems to avoid the problem; I don't have the slightest
idea whether that's the "right" way to do it, though.   (There may be a similar
problem with ChunkBrowserMethodDefinitionChunk>>restore, but I'm not sure about
that either.)

I still don't know why my workspace expression showed the bug for a while, then
stopped.  But since I /still/ can't make it "work" again, I've given up and
shall put it down to some unknown (and unknowable) error on my part.

    -- chris