8068886: IDEA IntelliJ crashes in objc_msgSend when an accessibility tool is enabled

Reviewed-by: serb, bae
This commit is contained in:
Anton Nashatyrev 2015-06-04 16:18:14 +03:00
parent bf336b750a
commit b7baec04e0
4 changed files with 41 additions and 3 deletions

View File

@ -23,6 +23,7 @@
* questions.
*/
#import <Cocoa/Cocoa.h>
#import <JavaNativeFoundation/JavaNativeFoundation.h>
#import "sun_lwawt_macosx_CFRetainedResource.h"
@ -37,7 +38,10 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CFRetainedResource_nativeCFRelease
(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 {

View File

@ -516,8 +516,10 @@ JNF_COCOA_ENTER(env);
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) {

View File

@ -37,6 +37,7 @@
- (void) registerWithProcessManager;
- (void) setDockIconWithEnv:(JNIEnv *)env;
- (void) postDummyEvent;
- (void) postRunnableEvent:(void (^)())block;
- (void) waitForDummyEvent;
+ (void) runAWTLoopWithApp:(NSApplication*)app;

View File

@ -337,9 +337,13 @@ AWT_ASSERT_APPKIT_THREAD;
- (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 @@ AWT_ASSERT_APPKIT_THREAD;
}
}
/*
* 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;