8068886: IDEA IntelliJ crashes in objc_msgSend when an accessibility tool is enabled
authoranashaty
Thu, 04 Jun 2015 16:18:14 +0300
changeset 31170 4d414cfb92cc
parent 31169 0647b79041f2
child 31171 59d8e7712c0b
8068886: IDEA IntelliJ crashes in objc_msgSend when an accessibility tool is enabled Reviewed-by: serb, bae
jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m
jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m
jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h
jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m	Thu Jun 04 15:24:30 2015 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m	Thu Jun 04 16:18:14 2015 +0300
@@ -23,6 +23,7 @@
  * questions.
  */
 
+#import <Cocoa/Cocoa.h>
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 
 #import "sun_lwawt_macosx_CFRetainedResource.h"
@@ -37,7 +38,10 @@
 (JNIEnv *env, jclass clazz, jlong ptr, jboolean releaseOnAppKitThread)
 {
     if (releaseOnAppKitThread) {
-        [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
+        // Releasing resources on the main AppKit message loop only
+        // Releasing resources on the nested loops may cause dangling 
+        // pointers after the nested loop is exited 
+        [NSApp postRunnableEvent:^(){
             CFRelease(jlong_to_ptr(ptr));
         }];
     } else {
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m	Thu Jun 04 15:24:30 2015 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m	Thu Jun 04 16:18:14 2015 +0300
@@ -516,8 +516,10 @@
                                              beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]];
         if (processEvents) {
             //We do not spin a runloop here as date is nil, so does not matter which mode to use
+            // Processing all events excluding NSApplicationDefined which need to be processed 
+            // on the main loop only (those events are intended for disposing resources)
             NSEvent *event;
-            if ((event = [NSApp nextEventMatchingMask:NSAnyEventMask
+            if ((event = [NSApp nextEventMatchingMask:(NSAnyEventMask & ~NSApplicationDefined)
                                            untilDate:nil
                                               inMode:NSDefaultRunLoopMode
                                              dequeue:YES]) != nil) {
--- a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h	Thu Jun 04 15:24:30 2015 +0300
+++ b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h	Thu Jun 04 16:18:14 2015 +0300
@@ -37,6 +37,7 @@
 - (void) registerWithProcessManager;
 - (void) setDockIconWithEnv:(JNIEnv *)env;
 - (void) postDummyEvent;
+- (void) postRunnableEvent:(void (^)())block;
 - (void) waitForDummyEvent;
 
 + (void) runAWTLoopWithApp:(NSApplication*)app;
--- a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m	Thu Jun 04 15:24:30 2015 +0300
+++ b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m	Thu Jun 04 16:18:14 2015 +0300
@@ -337,9 +337,13 @@
 
 - (void)sendEvent:(NSEvent *)event
 {
-    if ([event type] == NSApplicationDefined && TS_EQUAL([event timestamp], dummyEventTimestamp)) {
+    if ([event type] == NSApplicationDefined && TS_EQUAL([event timestamp], dummyEventTimestamp) && [event subtype] == 0) {
         [seenDummyEventLock lockWhenCondition:NO];
         [seenDummyEventLock unlockWithCondition:YES];
+    } else if ([event type] == NSApplicationDefined && [event subtype] == 777) {
+        void (^block)() = (void (^)()) [event data1];
+        block();
+        [block release];
     } else if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask)) {
         // Cocoa won't send us key up event when releasing a key while Cmd is down,
         // so we have to do it ourselves.
@@ -349,6 +353,33 @@
     }
 }
 
+/*
+ * Posts the block to the AppKit event queue which will be executed 
+ * on the main AppKit loop. 
+ * While running nested loops this event will be ignored. 
+ */
+- (void)postRunnableEvent:(void (^)())block 
+{
+    void (^copy)() = [block copy];
+    NSInteger encode = (NSInteger) copy;
+    [copy retain];
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];    
+    NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined
+                                        location: NSMakePoint(0,0)
+                                   modifierFlags: 0
+                                       timestamp: 0
+                                    windowNumber: 0
+                                         context: nil
+                                         subtype: 777
+                                           data1: encode
+                                           data2: 0];
+
+    [NSApp postEvent: event atStart: NO];
+    [pool drain];
+}
+
+
+
 - (void)postDummyEvent {
     seenDummyEventLock = [[NSConditionLock alloc] initWithCondition:NO];
     dummyEventTimestamp = [NSProcessInfo processInfo].systemUptime;