supplementalTargetForAction times out during Power Box sheet close
| Originator: | curtis.clifton | ||
| Number: | rdar://12342164 | Date Originated: | 2012-09-20 |
| Status: | Open | Resolved: | |
| Product: | Mac OS X | Product Version: | 10.8.2 |
| Classification: | Performance | Reproducible: | Always |
Summary: The foo for a Power Box sheet remains in the responder chain during toolbar re-validation after the user clicks a button to dismiss the sheet. During this time, calls to -[NSResponder supplementalTargetForAction] on the NSLocalWindowWrappingRemoteWindow instance which encapsulates the sheet result in dispatch_semaphore_wait time-outs. Steps to Reproduce: Build and run the attached sample project on 10.8 using Xcode 4.5. Click the button in the window. (Now would be a good time to clear your debug console.) Now click the Cancel button in the open sheet. Notice in the console that calls to supplementalTargetForAction on NSLocalWindowWrappingRemoteWindow take about 300 ms to return. Even though the sheet dismisses, notice that the window's UI remains unresponsive---the window close button is even grayed out---until after all toolbar buttons have been validated. Turn off logging of supplementalTargetForAction using the checkbox and repeat the experiment. Notice that the window becomes response much more quickly (though still much slower than when sandboxing is disabled). Expected Results: -[NSLocalWindowWrappingRemoteWindow supplementalTargetForAction] should return nil immediately if Power Box isn't able to respond, or else NSLocalWindowWrappingRemoteWindow should be removed as key window before revalidating the toolbar. Actual Results: -[NSLocalWindowWrappingRemoteWindow supplementalTargetForAction] times out for every call between dismissing the sheet and the instances eventually removal as the key window. Regression: Yes. The problem exists on 10.8.2. The problem does NOT exist on 10.7.5. Notes: We're hitting a nasty interaction of Power Box and -supplementalTargetForAction. The problem appears as a four second blocking of our UI after closing an NSOpenPanel sheet. AppKit uses the private class NSLocalWindowWrappingRemoteWindow to shove the open sheet into our window but redirect to Power Box for the internals. When the user clicks cancel or open in the open sheet, the sheet loses key, and AppKit revalidates all the toolbar items. The NSLocalWindowWrappingRemoteWindow instance is still in the responder chain at this point. We're using a custom target-selection mechanism, called OATargetSelection. OATargetSelection is triggered by an override of -[NSApplication targetForAction:to:from:]. That mechanism traverses the responder chain from the first responder of the key window and the main window. It also checks things like delegates, window controllers, and---crucially---supplementalTargetForAction. OATargetSelection calls supplementalTargetForAction on the NSLocalWindowWrappingRemoteWindow instance. NSLocalWindowWrappingRemoteWindow's supplementalTargetForAction dispatches to the Power Box instance, which doesn't respond. It's busy going away. The IPC call times out in 300 ms, supplementalTargetForAction returns nil, and we merrily chase the rest of the responder chain. Debugging shows that the time out occurs in _dispatch_semaphore_wait_slow, which is tail-called by dispatch_semaphore_wait. The time-out argument to dispatch_semaphore_wait is generated by a call to dispatch_time with a time-out offset of 300,000,000 nanoseconds. That matches the 300 ms delay we observe. Further the return code of _dispatch_semaphore_wait_slow is 49, indicating a time-out. This time-out delay happens for every validation. After the four seconds that this consumes, the sheet finally leaves the responder chain, our completion handler for the open sheet is called, and the UI becomes responsive again. The delay goes away if we don't call supplementalTargetForAction, but we know of no way to do that only during the sheet closing process. We must call it during regular display of the sheet so that things like edit menu items are validated correctly. The delay also goes away if we turn off sandboxing, but we are working hard to support sandboxing for new versions of our applications. Attempted work-arounds and their failures: - We attempted to register for NSWindowDidEndSheetNotification. Debugging indicates that this notification is posted to the notification center before the problemantic toolbar validation; however, it isn't propagated until _after_ the validation and corresponding time outs. - We attempted to use -[NSApplication endSheet:returnCode:], but that isn't called until after a second round of toolbar validation that comes after the NSWindowDidEndSheetNotification.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!