[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Argh! Bundle loading bug...
From: |
Nicola Pero |
Subject: |
Re: Argh! Bundle loading bug... |
Date: |
Mon, 25 Feb 2002 18:05:46 +0000 (GMT) |
I looked at the bundle code and ... well I see your problem.
Let me guess what happens in a typical situation (may be it's just your
situation) ... you have a bundle. Inside the bundle you have a class, and
some resources. You load the bundle, instantiate an instance of the
class. At some point later on, an object of this class needs access to
its resources. So, it calls '[NSBundle bundleForClass: [self class]]' to
get its own bundle. And I'm pretty that that will never work.
The reason why it doesn't work is that the bundle holding the class has
been released - and put into a `released bundles' array, which is hidden.
+bundleForClass: loops on the existing non-released bundles (which doesn't
include the 'released bundles' array) searching for the class, and doesn't
find it because the bundle holding that class is not in the list.
Of course something is seriously wrong here :-)
My opinion is that we should simplify the code in the following way -
- if a bundle has not loaded any code, it is managed normally. It can
be deallocated at any point in time (it would be nice if we would
remove the +gnustepBundle and all the special code to manage it in
a special way).
- if a bundle has loaded code, it is never freed. (that includes the
main bundle, and perhaps it's not a special case - we might reasonably
set _codeLoaded to YES at application startup for the main bundle).
By 'it is never freed' I mean we just ignore release messages. The
bundle must always be available, because at any time someone might
call 'bundleForClass:' for a class which was loaded by that bundle,
and the bundle must be known so that we find the it. (if an
application is scanning classes in bundles using some other mechanism,
it is probably going to call +allBundles and loop on the bundles
returned, inspecting the classes of each of them in some way. For this
reason +allBundles should always return all bundles from which we have
loaded some code. That is the main reason it exists as far as I
understand.)
If we ever support unloading object code and classes (I doubt that),
then once we unload an object/class, we can destroy the bundle which
loaded it.
So, the main change I propose is removing the obscure _releasedBundles
map, and just ignore all release messages sent to bundles which have
loaded any code.
That will fix +bundleForClass: to work regardless of the retain count of
the original NSBundle object which loaded the code; it will fix
+allBundles: to return all bundles which have loaded some code (so that
you can use it to scan bundles for classes); and it will simplify code.
Basically, the idea is that once you've loaded code from a bundle, that
bundle object is needed by the base library to look up the bundle which
loaded a certain class. So in a certain sense, the base library retains
it. We could actually implement pretty elegantly in that way - we retain
the bundles we load when we load them - then we can remove any custom
retain count or similar stuff. We would release them in the unload method
if we had it.
Any particular objections ?
> Hi,
>
> OK, I've narrowed down my problem. I just take a look at the list of
> bundles with the following code:
>
> NSArray *allBundles; int i;
>
> allBundles = [NSBundle allBundles];
> for(i=0; i<[allBundles count]; i++)
> printf(" Bundle %d: %@\n", i,
> [[allBundles objectAtIndex: i] bundlePath]);
>
> ...and this is what I get:
>
> - From main program immediately after loading the bundle:
>
> Bundle 0: /usr/GNUstep/Local/Library/Bundles/CodeEditorBundle.bundle
> Bundle 1: /usr/GNUstep/Local/Libraries
> Bundle 2: /usr/GNUstep/System/Apps/CodeEditor.app
> Bundle 3: /usr/GNUstep/System/Libraries/Resources/gnustep-gui
> Bundle 4: /usr/GNUstep/System/Libraries
>
> (here, bundle 0 is what I want.)
>
> - From a class in the bundle, later:
>
> Bundle 0: /usr/GNUstep/System/Apps/CodeEditor.app
> Bundle 1: /usr/GNUstep/System/Libraries/Resources/gnustep-gui
> Bundle 2: /usr/GNUstep/System/Libraries
>
> What is happening here? Where do the first two entries disappear to? Help!
- Re: Argh! Bundle loading bug...,
Nicola Pero <=