Changeset 19458 in webkit


Ignore:
Timestamp:
Feb 6, 2007 7:50:43 PM (17 years ago)
Author:
kdecker
Message:

Fixed: <rdar://problem/4976681> ASSERTION failure on quit @ talkcrunch.com in _NPN_ReleaseObject


Reviewed by Anders.

  • Plugins/WebPluginDatabase.m: (+[WebPluginDatabase sharedDatabase]): Removed NSApplicationWillTerminateNotification observer and thus also removed code that would unload the entire plug-in database when receiving that notification.


The bug here was that this notification callback would happen first before anything else thus unloading
plug-ins and releasing plug-in memory. That was crash prone because the JavaScriptCore collector would at
a later time attempt to release its CInstance references (references that point to plug-in memory)
without knowing WebKit already unloaded the plug-in out from underneath it. The WebPluginDatabase simply
does not have enough context to make this decision.


  • WebView/WebView.mm: Added two statics: applicationIsTerminating, pluginDatabaseClientCount. (+[WebView initialize]): Added NSApplicationWillTerminateNotification observer. (+[WebView _applicationWillTerminate]): Added. (-[WebView _close]): WebKit has both a global plug-in database and a separate, per WebView plug-in database. We need to release both sets of plug-ins because Netscape plug-ins have "destructor functions" that should be called when the browser unloads the plug-in. These functions can do important things, such as closing/deleting files so it is important to ensure that they are properly called when the application terminates.


The new change is that on app shutdown, we unload WebKit's global plug-in database if and only if the last WebView
was closed. To do so otherwise would unload plug-ins out from underneath other WebViews.

Location:
trunk/WebKit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebKit/ChangeLog

    r19449 r19458  
     12007-02-06  Kevin Decker <kdecker@apple.com>
     2
     3        Fixed: <rdar://problem/4976681> ASSERTION failure on quit @ talkcrunch.com in _NPN_ReleaseObject
     4       
     5        Reviewed by Anders.
     6
     7        * Plugins/WebPluginDatabase.m:
     8        (+[WebPluginDatabase sharedDatabase]): Removed NSApplicationWillTerminateNotification observer and thus
     9        also removed code that would unload the entire plug-in database when receiving that notification.
     10       
     11        The bug here was that this notification callback would happen first before anything else thus unloading
     12        plug-ins and releasing plug-in memory. That was crash prone because the JavaScriptCore collector would at
     13        a later time attempt to release its CInstance references (references that point to plug-in memory)
     14        without knowing WebKit already unloaded the plug-in out from underneath it. The WebPluginDatabase simply
     15        does not have enough context to make this decision.
     16       
     17        * WebView/WebView.mm: Added two statics: applicationIsTerminating, pluginDatabaseClientCount.
     18        (+[WebView initialize]): Added NSApplicationWillTerminateNotification observer.
     19        (+[WebView _applicationWillTerminate]): Added.
     20        (-[WebView _close]): WebKit has both a global plug-in database and a separate, per WebView plug-in database.
     21         We need to release both sets of plug-ins because Netscape plug-ins have "destructor functions" that should be
     22         called when the browser unloads the plug-in.  These functions can do important things, such as closing/deleting
     23         files so it is important to ensure that they are properly called when the application terminates.
     24         
     25         The new change is that on app shutdown, we unload WebKit's global plug-in database if and only if the last WebView
     26         was closed. To do so otherwise would unload plug-ins out from underneath other WebViews.
     27         
    1282007-02-06  Darin Adler  <darin@apple.com>
    229
  • trunk/WebKit/Plugins/WebPluginDatabase.m

    r18424 r19458  
    4848- (void)_removePlugin:(WebBasePluginPackage *)plugin;
    4949- (NSMutableSet *)_scanForNewPlugins;
    50 - (void)_applicationWillTerminate;
    5150@end
    5251
     
    6160        [sharedDatabase setPlugInPaths:[self _defaultPlugInPaths]];
    6261        [sharedDatabase refresh];
    63        
    64         // Clear the global plug-in database on app exit
    65         [[NSNotificationCenter defaultCenter] addObserver:sharedDatabase
    66                                                  selector:@selector(_applicationWillTerminate)
    67                                                      name:NSApplicationWillTerminateNotification
    68                                                    object:NSApp];
    6962    }
    7063   
     
    375368}
    376369
    377 - (void)_applicationWillTerminate
    378 {
    379     ASSERT(self == sharedDatabase);
    380     // Remove all plug-ins from database.  Netscape plug-ins have "destructor functions" that should be called
    381     // when the browser unloads the plug-in.  These functions can do important things, such as closing/deleting files,
    382     // so it is important to ensure that they are properly called when the application terminates.
    383     [self close];
    384 }
    385 
    386370@end
  • trunk/WebKit/WebView/WebView.mm

    r19295 r19458  
    232232macro(yankAndSelect) \
    233233
     234static BOOL applicationIsTerminating;
     235static int pluginDatabaseClientCount = 0;
     236
    234237@interface NSSpellChecker (AppKitSecretsIKnow)
    235238- (void)_preflightChosenSpellServer;
     
    308311    BOOL selectWordBeforeMenuEvent;
    309312   
     313    // WebKit has both a global plug-in database and a separate, per WebView plug-in database. Dashboard uses the per WebView database.
    310314    WebPluginDatabase *pluginDatabase;
    311315   
     
    392396    if (!self)
    393397        return nil;
    394    
    395398    allowsUndo = YES;
    396399    textSizeMultiplier = 1;
     
    398401    shouldCloseWithWindow = objc_collecting_enabled();
    399402    continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
     403
    400404#ifndef BUILDING_ON_TIGER
    401405    grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
     
    404408   
    405409    identifierMap = new HashMap<unsigned long, RetainPtr<id> >();
     410    pluginDatabaseClientCount++;
    406411
    407412    return self;
     
    652657        _private->hasSpellCheckerDocumentTag = NO;
    653658    }
    654 
     659   
     660    [[NSNotificationCenter defaultCenter] removeObserver:self];
     661    [WebPreferences _removeReferenceForIdentifier: [self preferencesIdentifier]];
     662    pluginDatabaseClientCount--;
     663   
     664    // Make sure to close both sets of plug-ins databases because plug-ins need an opportunity to clean up files, etc.
     665   
     666    // Unload the WebView local plug-in database.
    655667    if (_private->pluginDatabase) {
    656668        [_private->pluginDatabase close];
     
    658670        _private->pluginDatabase = nil;
    659671    }
    660 
    661     [[NSNotificationCenter defaultCenter] removeObserver:self];
    662 
    663     [WebPreferences _removeReferenceForIdentifier: [self preferencesIdentifier]];
     672   
     673    // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
     674    if (!pluginDatabaseClientCount && applicationIsTerminating)
     675        [[WebPluginDatabase sharedDatabase] close];
    664676}
    665677
     
    14441456// this prevents open source users from crashing when using the Show DOM Tree menu item in Safari
    14451457// FIXME: remove this when it is no longer needed to prevent Safari from crashing
    1446 +(void)initialize
     1458+ (void)initialize
    14471459{
    14481460    static BOOL tooLate = NO;
     
    14501462        if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"] && [[NSUserDefaults standardUserDefaults] boolForKey:@"IncludeDebugMenu"])
    14511463            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_finishedLaunching) name:NSApplicationDidFinishLaunchingNotification object:NSApp];
     1464       
     1465        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
    14521466        tooLate = YES;
    14531467    }
    14541468}
    14551469
    1456 +(void)_finishedLaunching
     1470+ (void)_applicationWillTerminate
     1471{   
     1472    applicationIsTerminating = YES;
     1473    if (!pluginDatabaseClientCount)
     1474        [[WebPluginDatabase sharedDatabase] close];
     1475}
     1476
     1477+ (void)_finishedLaunching
    14571478{
    14581479    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_removeDOMTreeMenuItem:) name:NSMenuDidAddItemNotification object:[NSApp mainMenu]];
Note: See TracChangeset for help on using the changeset viewer.