title: NSOpenPanel.runModal + NSAlert.runModal over GCD cause a hang
body: <p>In my Cocoa application I have some computations done in the background. The background work is runned with <code>DispatchQueue.global(qos: .utility).async</code>.
  This background task may report errors by showing a modal <code>NSAlert</code> via <code>DispatchQueue.main.async</code>.</p>
  <p>Also, in my application user can run <code>NSOpenPanel</code> to open some files (with <code>NSOpenPanel.runModal</code>).</p>
  <p>The problem is that if the user opens <code>NSOpenPanel</code> and at the same time the background task shows <code>NSAlert</code>, the application may hang.</p>
  <ul>
  <li>user opens modal <code>NSOpenPanel</code></li>
  <li>background task opens modal <code>NSAlert</code> atop the <code>NSOpenPanel</code></li>
  <li>user clicks <em>Close</em> inside <code>NSOpenPanel</code> (it really can access <code>NSOpenPanel</code> despite the more modal <code>NSAlert</code> present).</li>
  <li>both <code>NSAlert</code> and <code>NSOpenPanel</code> being closed and application hangs with main thread blocked inside <code>NSOpenPanel.runModal()</code></li>
  <li>application will not hang if user first close <code>NSAlert</code> and then <code>NSOpenPanel</code>.</li>
  </ul>
  <p>The minimal code sample (the test IBaction is binded as the action for the button in the main window)</p>
  <pre><code>import Cocoa
  
  @NSApplicationMain
  class AppDelegate: NSObject, NSApplicationDelegate {
  
      @IBOutlet weak var window: NSWindow!
     
      @IBAction func test(_ sender: Any) {
          //run some work in background
          DispatchQueue.global(qos: .utility).async
          {
              sleep(1) //some work
  
              //report errors in the main thread.
              DispatchQueue.main.async {
                  let alert = NSAlert();
                  alert.informativeText = &quot;Close NSOpen panel before this alert to reproduct the hang.&quot;
                  alert.runModal()
              }
          }
          
          //user want to open a file and opens the open file dialog
          let dlg = NSOpenPanel();
          dlg.runModal();
      }
  }
  
  </code></pre>
  <p>So, what's wrong with this code and why it cause the hang in particular use cases? And how can I prevent such a hang?</p>
  <p>Additional note: I discovered, then if I replace <code>dlg.runModal()</code> with <code>NSApp.RunModal(for: dlg)</code> (which is exactly the same as per Apple documentation), this will fix hang in the usecase described above.
  But it still will close <code>NSAlert</code> automatically right after closing <code>NSOpenPanel</code>. And I still can't understood why this behave as it does.</p>
  <h2>Update</h2>
  <p>I updated the code above to include full code of AppDelegate class of minimal reproducible application. To reproduce the case, just create new SwiftApp in XCode, replace AppDelegate code, add button in the main window and wire button's action with <code>test</code> func. I also placed full ready-to-compile project on github: <a href="https://github.com/snechaev/hangTest" rel="nofollow noreferrer">https://github.com/snechaev/hangTest</a></p>
  <p>The code for configuring NSOpenPanel and NSAlert along with their results handling is excluded as such a code does not affect the hang.</p>