[8] Review request for 7170716: JVM crash when opening an AWT app from a registered file. [WAS: Re: Patch for #7170716, crash in OSXAPP_SetApplicationDelegate]
Anthony Petrov
anthony.petrov at oracle.com
Wed Jun 13 06:08:26 PDT 2012
Hi Marco,
Thank you for investigating the issue and developing a fix. I've
uploaded a webrev for your patch at:
http://cr.openjdk.java.net/~anthony/8-34-crashInSetApplicationDelegate-7170716.0/
I've got a concern regarding the retain calls on the delegate instance.
With your fix we retain it for the first time at
OSXAPP_SetApplicationDelegate(), and then one more time at
QAD.processQueuedEventsWithTargetDelegate. However, we never release the
object. Moreover, I believe that the NSApplication setDelegate: call
also retains it.
I'd think that we can retain it in the beginning of the
OSXAPP_SetAppDelegate(), and then release it in the end. And we don't
need a retain call in the processQEWTD. Could you please verify this?
--
best regards,
Anthony
On 6/11/2012 8:17 PM, Marco Dinacci wrote:
> Hi,
>
> I raised a couple of weeks ago bug #7170716 :
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7170716
>
> The original discussion is here:
> http://mail.openjdk.java.net/pipermail/macosx-port-dev/2012-May/004226.html
>
> In short, every time a Java application is opened from a registered
> file the JVM crash in OSXAPP_SetApplicationDelegate.
>
> Today I started looking for a solution and I've found two memory
> management issues in the code:
>
> The first and the one that was causing the bug is related with blocks.
> In QueuingApplicationDelegate.m there are many methods where you're
> adding blocks to an NSMutableArray but without copying them.
> Those blocks literals are created on the stack so even if they're
> retained once the function exits they no longer exist. Calling [copy]
> will assure that the block will have a reference on the heap. Then
> once the block has been consumed it needs to be released.
>
> The second issue is that you don't retain the delegate object in
> QueuingApplicationDelegate.m and in NSApplicationAWT.m.
> Even if the pointers are static you should still call [retain] because
> it's not guaranteed that the objects the pointers are pointing to
> won't be deallocated at one point.
>
> Here below a patch that resolve both issues, I tested it successfully
> with a trivial test case and with my application.
>
> Best,
> Marco
>
> diff -r 96dd3a52e76c src/macosx/native/sun/osxapp/NSApplicationAWT.m
> --- a/src/macosx/native/sun/osxapp/NSApplicationAWT.m Thu May 31
> 16:35:25 2012 +0100
> +++ b/src/macosx/native/sun/osxapp/NSApplicationAWT.m Mon Jun 11
> 16:49:04 2012 +0100
> @@ -334,17 +334,17 @@ AWT_ASSERT_APPKIT_THREAD;
> }
>
> @end
>
>
> void OSXAPP_SetApplicationDelegate(id <NSApplicationDelegate> delegate)
> {
> AWT_ASSERT_APPKIT_THREAD;
> - applicationDelegate = delegate;
> + applicationDelegate = [delegate retain];
>
> if (NSApp != nil) {
> [NSApp setDelegate: applicationDelegate];
>
> if (applicationDelegate && qad) {
> [qad processQueuedEventsWithTargetDelegate: applicationDelegate];
> qad = nil;
> }
> diff -r 96dd3a52e76c src/macosx/native/sun/osxapp/QueuingApplicationDelegate.m
> --- a/src/macosx/native/sun/osxapp/QueuingApplicationDelegate.m Thu
> May 31 16:35:25 2012 +0100
> +++ b/src/macosx/native/sun/osxapp/QueuingApplicationDelegate.m Mon
> Jun 11 16:49:04 2012 +0100
> @@ -104,110 +104,110 @@ static id <NSApplicationDelegate> realDe
> self->queue = nil;
>
> [super dealloc];
> }
>
>
> - (void)_handleOpenURLEvent:(NSAppleEventDescriptor *)openURLEvent
> withReplyEvent:(NSAppleEventDescriptor *)replyEvent
> {
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [realDelegate _handleOpenURLEvent:openURLEvent
> withReplyEvent:replyEvent];
> - }];
> + } copy]];
> }
>
> - (void)application:(NSApplication *)theApplication
> openFiles:(NSArray *)fileNames
> {
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [realDelegate application:theApplication openFiles:fileNames];
> - }];
> + } copy]];
> }
>
> - (NSApplicationPrintReply)application:(NSApplication *)application
> printFiles:(NSArray *)fileNames withSettings:(NSDictionary
> *)printSettings showPrintPanels:(BOOL)showPrintPanels
> {
> if (!fHandlesDocumentTypes) {
> return NSPrintingCancelled;
> }
>
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [realDelegate application:application printFiles:fileNames
> withSettings:printSettings showPrintPanels:showPrintPanels];
> - }];
> + } copy]];
>
> // well, a bit premature, but what else can we do?..
> return NSPrintingSuccess;
> }
>
> - (void)_willFinishLaunching
> {
> - QueuingApplicationDelegate * q = self;
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [[realDelegate class] _willFinishLaunching];
> - }];
> + } copy]];
> }
>
> - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication
> hasVisibleWindows:(BOOL)flag
> {
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [realDelegate applicationShouldHandleReopen:theApplication
> hasVisibleWindows:flag];
> - }];
> + } copy]];
> return YES;
> }
>
> - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app
> {
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [realDelegate applicationShouldTerminate:app];
> - }];
> + } copy]];
> return NSTerminateLater;
> }
>
> - (void)_systemWillPowerOff
> {
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [[realDelegate class] _systemWillPowerOff];
> - }];
> + } copy]];
> }
>
> - (void)_appDidActivate
> {
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [[realDelegate class] _appDidActivate];
> - }];
> + } copy]];
> }
>
> - (void)_appDidDeactivate
> {
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [[realDelegate class] _appDidDeactivate];
> - }];
> + } copy]];
> }
>
> - (void)_appDidHide
> {
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [[realDelegate class] _appDidHide];
> - }];
> + } copy]];
> }
>
> - (void)_appDidUnhide
> {
> - [self->queue addObject:^(){
> + [self->queue addObject:[^(){
> [[realDelegate class] _appDidUnhide];
> - }];
> + } copy]];
> }
>
> - (void)processQueuedEventsWithTargetDelegate:(id
> <NSApplicationDelegate>)delegate
> {
> + realDelegate = [delegate retain];
> +
> NSUInteger i;
> NSUInteger count = [self->queue count];
>
> - realDelegate = delegate;
> -
> for (i = 0; i < count; i++) {
> void (^event)() = (void (^)())[self->queue objectAtIndex: i];
> event();
> + [event release];
> }
>
> [self->queue removeAllObjects];
> }
>
> @end
More information about the macosx-port-dev
mailing list