bug-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ 100307 ] Dynamic loading of .framework broken?


From: nobody
Subject: [ 100307 ] Dynamic loading of .framework broken?
Date: Sat, 12 Jan 2002 22:18:52 -0500

Support Request #100307, was updated on 2002-Jan-12 22:18
You can respond by visiting: 
http://savannah.gnu.org/support/?func=detailsupport&support_id=100307&group_id=99

Category: Foundation
Status: Open
Priority: 5
Summary: Dynamic loading of .framework broken?

By: kaelin
Date: 2002-Jan-12 22:18

Message:
Logged In: NO 
Browser: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.5) Gecko/20011014

The NSBundle (Private) method _addFrameworkFromClass:
gets called in the callback chain from dlopen when a
framework is dynamically loaded, e.g.:

NSBundle * classBundle = [NSBundle bundleWithPath:
@"/usr/share/pvm3/Library/Frameworks/FWBench.framework"];
if ([classBundle load]) {
  ...
}

In the current CVS version of the Foundation sources,
_addFrameworkFromClass: tries and (at least in some
common cases) fails to reconstruct bundlePath from thin
air, then ends up trying to allocate a new NSBundle
instance with a nil path. Initially this is just logged
as a warning, but eventually this leads to a SEGV.

I have made a stab at fixing the immediate problem, and
my code is included here. This fix does appear to work
for me, BUT I am concerned that it might have unforseen
consequences in use cases I'm just not exercising... or
that it's completely the wrong thing because I don't
know the runtime architecture well enough to muck with
this!

My changes are explained in the comments...

+ (BOOL) _addFrameworkFromClass:(Class)frameworkClass
{
  int             len;

  if (frameworkClass == Nil)
    return NO;

  len = strlen(frameworkClass->name);

  if (len > 12*sizeof(char)
    && !strncmp("NSFramework_", frameworkClass->name,
sizeof(char)*12))
    {
      NSBundle   *bundle = _loadingBundle;
      NSString  **fmClasses;

      /*
       * This following block used to be executed
unconditionally, and
       * would ultimately fail when a framework's code
was being
       * dynamically loaded because it was allocating a
new NSBundle
       * instance and initializing its path to nil. Now
we are first
       * checking _loadingBundle, and if non-nil we
initialize the
       * existing bundle instead of creating a new one.
       * -- Kaelin 01/13/2002
       */
      if (bundle == nil) {
        NSString *bundlePath = nil;
        NSString *varEnv, *path, *name;

        name = [NSString stringWithCString:
&frameworkClass->name[12]];
        
        varEnv = [frameworkClass frameworkEnv];
        if (varEnv && [varEnv length])
          bundlePath = [[[NSProcessInfo processInfo] environment]
                         objectForKey: varEnv];
        
        path = [frameworkClass frameworkPath];
        if (path && [path length])
          {
            if (bundlePath)
              bundlePath = [bundlePath
stringByAppendingPathComponent: path];
            else
              bundlePath = path;
          }
        else
          bundlePath = [bundlePath
                stringByAppendingPathComponent: @"Library/Frameworks"];
        
        bundlePath = [bundlePath stringByAppendingPathComponent:
                [NSString stringWithFormat: @"%@.framework", name]];
        
        bundle = [[NSBundle alloc] initWithPath: bundlePath];
      }
      
      bundle->_bundleType = NSBUNDLE_FRAMEWORK;
      bundle->_codeLoaded = YES;
      bundle->_frameworkVersion =
RETAIN([frameworkClass frameworkVersion]);
      bundle->_bundleClasses = RETAIN([NSMutableArray
arrayWithCapacity: 2]);

      fmClasses = [frameworkClass frameworkClasses];

      while (*fmClasses)
        {
          NSValue *value;
          Class    class = NSClassFromString(*fmClasses);

          value = [NSValue valueWithNonretainedObject: class];

          [(NSMutableArray *)[bundle _bundleClasses] addObject:
value];

#if 0     /*
           * This isn't needed anymore, because now if we're
loading a
           * bundle, that's the one we just updated...
           */
          if (_loadingBundle)
            {
              NSEnumerator *classEnum;
              NSValue      *obj;

              classEnum = [_loadingBundle->_bundleClasses
objectEnumerator];
              while ((obj = [classEnum nextObject]))
                {
                  if ([obj nonretainedObjectValue] == class)
                    {
                      [(NSMutableArray *)_loadingBundle->_bundleClasses
                        removeObject: obj];
                      break;
                    }
                }
            }
#endif

          fmClasses++;
        }

      return YES;
    }

  return NO;
}


----------------------------------------------------------------------
You can respond by visiting: 
http://savannah.gnu.org/support/?func=detailsupport&support_id=100307&group_id=99



reply via email to

[Prev in Thread] Current Thread [Next in Thread]