Date   
Re: Canceling NSSavePanel Hang App

Rafael Bugajewski
 

Hi Sandor,

from the stacks it looks like you’ve Finder Extensions installed on your system. Can you disable / uninstall them and verify if the issue is still reproducible?

Best,
Rafał

On 2020-01-04, at 11:31 PM, Sandor Szatmari <admin.szatmari.net@...> wrote:

Ran into an interesting issue today…
Mac app
Xcode 9.4.1, 32bit, 10.12 SDK, 10.6 Deployment Target
non-sandboxed app

I am opening an NSSavePanel to allow a user to save the results of a report that is to be generated.

// Creating the save panel
NSSavePanel* savePanel = [NSSavePanel savePanel];
[savePanel setTitle:[NSString stringWithFormat:@"Export %@ Summary Data for %@", [self selectedReport], customerName]];

Opening the NSSavePanel using -runModal
savePanelUserAction = [savePanel runModal];

If the user enters a filename and clicks continue the save dialog closes, the report is generated, and the file is written to disk at the selected location.
if (savePanelUserAction == NSFileHandlingPanelOKButton)
[NSThread detachNewThreadSelector:@selector(createSummary:) toTarget:self withObject:[[savePanel URL] path]];

If the user clicks cancel, the program hangs. It hangs so badly that I have to go to the System Force-Quit dialog in order to fully terminate the app.
(i.e. Clicking stop program in Xcode does not fully terminate the app)
else
{
// Program hangs
}

I have checked that the NSSavePanel is being opened from the main thread.
I have included interesting backtraces below that are present if I stop the app in the de

Sandor

Thread 1 Queue : com.apple.main-thread (serial)
#0 0xa73d423e in kevent_id ()
#1 0x003305a6 in _dispatch_kq_poll ()
#2 0x00331141 in _dispatch_event_loop_wait_for_ownership ()
#3 0x00327b80 in _dispatch_sync_wait ()
#4 0x0031d500 in _dispatch_sync_f_slow ()
#5 0x0030f6d1 in dispatch_barrier_sync_f ()
#6 0x00316bf3 in dispatch_barrier_sync ()
#7 0x9387ebd4 in _VolumeObserverInvalidate ()
#8 0xa04ee78e in TSystemNotificationTask::~TSystemNotificationTask() ()
#9 0xa04ee818 in TSystemNotificationTask::FinalizeSystemNotificationTask() ()
#10 0xa04dda71 in NodeContextClose ()
#11 0x0afc689a in TFENode::Finalize() ()
#12 0x0b127290 in +[FIFinderViewGutsController finalizeCounted] ()
#13 0x0b127366 in __45+[FIFinderViewGutsController finalizeCounted]_block_invoke ()
#14 0x003167af in _dispatch_call_block_and_release ()
#15 0x0030e94d in _dispatch_client_callout ()
#16 0x0031ae6c in _dispatch_main_queue_callback_4CF ()
#17 0x937bb2ae in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#18 0x9377ecf4 in __CFRunLoopRun ()
#19 0x9377dbd1 in CFRunLoopRunSpecific ()
#20 0x9377d93a in CFRunLoopRunInMode ()
#21 0x92d7b37b in RunCurrentEventLoopInMode ()
#22 0x92d7b0a2 in ReceiveNextEventCommon ()
#23 0x92d7ad7b in _BlockUntilNextEventMatchingListInModeWithFilter ()
#24 0x9137aafd in _DPSNextEvent ()
#25 0x91aece90 in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] ()
#26 0x91aec35d in -[NSApplication(NSEvent) nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#27 0x9136fa4d in -[NSApplication run] ()
#28 0x91341b0a in NSApplicationMain ()
#29 0x000026bc in main at /Users/username/repo/AppName/main.m:13
#30 0x00002685 in start ()
Enqueued from TBrowserViewDataSource (Thread 14) Queue : TBrowserViewDataSource (serial)
#0 0x0033f4dc in _dispatch_introspection_queue_item_enqueue ()
#1 0x00325cf8 in _dispatch_queue_push ()
#2 0x00323230 in _dispatch_continuation_push ()
#3 0x0032259b in _dispatch_continuation_async ()
#4 0x00316173 in dispatch_async ()
#5 0x0b1272f6 in +[FIFinderViewGutsController finalizeCounted] ()
#6 0x0b1aa3af in -[FI_TBrowserViewDataSource dealloc] ()
#7 0xa67a09f9 in objc_object::sidetable_release(bool) ()
#8 0xa679e2d0 in -[NSObject release] ()
#9 0x0b1aa762 in __destroy_helper_block_ ()
#10 0xa72c6b75 in _Block_release ()
#11 0x0030e94d in _dispatch_client_callout ()
#12 0x00324d3a in _dispatch_queue_serial_drain ()
#13 0x003162e2 in _dispatch_queue_invoke ()
#14 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#15 0x0032b4bb in _dispatch_workloop_worker_thread ()
#16 0x00381601 in _pthread_wqthread ()
#17 0x0038121e in start_wqthread ()
Enqueued from com.apple.main-thread (Thread 1) Queue : com.apple.main-thread (serial)
#0 0x0033f4dc in _dispatch_introspection_queue_item_enqueue ()
#1 0x00325cf8 in _dispatch_queue_push ()
#2 0x00323230 in _dispatch_continuation_push ()
#3 0x0032259b in _dispatch_continuation_async ()
#4 0x00316173 in dispatch_async ()
#5 0x0b1aa460 in -[FI_TBrowserViewDataSource aboutToTearDown] ()
#6 0x0b1e0aa5 in -[FI_TBrowserContainerController destroyBrowserView:] ()
#7 0x0b1e3ed4 in -[FIContainerController destroyBrowserView:] ()
#8 0x0b1e06c6 in -[FI_TBrowserContainerController aboutToTearDown] ()
#9 0x0b1e3f3b in -[FIContainerController aboutToTearDown] ()
#10 0xa67a0bda in -[NSObject performSelector:] ()
#11 0x0b042f47 in AboutToTearDownViewController(NSViewController*) ()
#12 0x0b07a83c in -[FI_TBrowserContentViewController aboutToTearDown] ()
#13 0xa67a0bda in -[NSObject performSelector:] ()
#14 0x0b042f47 in AboutToTearDownViewController(NSViewController*) ()
#15 0x0b1293f0 in -[FIFinderViewGutsController prepareToHide] ()
#16 0x0b12996f in -[FIFinderViewGutsController windowOrderedOut] ()
#17 0x0b13486f in -[FIFinderView windowOrderedOut] ()
#18 0x91e3ffe5 in -[NSNavFinderViewFileBrowser windowOrderedOut] ()
#19 0x91a4df5e in -[NSSavePanel _navViewWindowOrderedOut] ()
#20 0x91a4dfc5 in -[NSSavePanel orderOut:] ()
#21 0x91a5bffa in -[NSSavePanel _didEndSheet:returnCode:contextInfo:] ()
#22 0x91c27b17 in NSWindowEndWindowModalSession ()
#23 0x915acaf6 in -[NSWindow _endWindowBlockingModalSession:returnCode:] ()
#24 0x915aca86 in -[NSWindow endSheet:returnCode:] ()
#25 0x915f7367 in -[NSApplication endSheet:returnCode:] ()
#26 0x91a5e2cb in -[NSSavePanel _dismissWindowWithReturnCode:willRunSeamlessOpening:] ()
#27 0x91a5e2f1 in -[NSSavePanel _cancelAndClose] ()
#28 0x91a5e933 in -[NSSavePanel cancel:] ()
#29 0xa67a0c1c in -[NSObject performSelector:withObject:] ()
#30 0x91aeeca9 in __49-[NSApplication(NSResponder) sendAction:to:from:]_block_invoke ()
#31 0x91aeec4d in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#32 0x91aeeb4f in -[NSApplication(NSResponder) sendAction:to:from:] ()
#33 0x9159eda8 in -[NSControl sendAction:to:] ()
#34 0x9159ecc7 in __26-[NSCell _sendActionFrom:]_block_invoke ()
#35 0x917e5009 in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#36 0x9159ec11 in -[NSCell _sendActionFrom:] ()
#37 0x915dd6cb in -[NSButtonCell _sendActionFrom:] ()
#38 0x917e6e2c in __48-[NSCell trackMouse:inRect:ofView:untilMouseUp:]_block_invoke.1099 ()
#39 0x917e5009 in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#40 0x9159d58d in -[NSCell trackMouse:inRect:ofView:untilMouseUp:] ()
#41 0x915dd420 in -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] ()
#42 0x9159bff4 in -[NSControl mouseDown:] ()
#43 0x91c922b4 in -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] ()
#44 0x91c9024f in -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] ()
#45 0x91c8e4c0 in -[NSWindow(NSEventRouting) sendEvent:] ()
#46 0x91aeb2d5 in -[NSApplication(NSEvent) sendEvent:] ()
#47 0x9136fa98 in -[NSApplication run] ()
#48 0x91341b0a in NSApplicationMain ()
#49 0x000026bc in main at /Users/username/repo/AppName/main.m:13
#50 0x00002685 in start ()


// Other threads that seemed interesting, but could be misleading???

Thread 2 Queue : com.apple.CFVolumeObserver.0x6af670 (serial)
#0 0xa73d242a in __getattrlist ()
#1 0x9ffa770f in volumePropertyProviderPrepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) ()
#2 0x9ffa1ebd in prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) ()
#3 0x9ff9f858 in _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) ()
#4 0x9ff9f779 in _FSURLCopyResourcePropertyForKey ()
#5 0x93765cd0 in CFURLCopyResourcePropertyForKey ()
#6 0x937dfaf6 in _VolumeObserverDiskAppearedCallback ()
#7 0x9513f6ab in _DADispatchCallback ()
#8 0x9513f439 in _DASessionCallback ()
#9 0x9513f304 in __DASessionSetDispatchQueue_block_invoke_2 ()
#10 0x0030e94d in _dispatch_client_callout ()
#11 0x00323464 in _dispatch_continuation_pop ()
#12 0x00310eba in _dispatch_source_invoke ()
#13 0x00324b73 in _dispatch_queue_serial_drain ()
#14 0x003162e2 in _dispatch_queue_invoke ()
#15 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#16 0x0032b4bb in _dispatch_workloop_worker_thread ()
#17 0x00381601 in _pthread_wqthread ()
#18 0x0038121e in start_wqthread ()


Thread 10 Queue : com.apple.CFVolumeObserver.0x6ac5d0 (serial)
#0 0xa73d242a in __getattrlist ()
#1 0x9ffa770f in volumePropertyProviderPrepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) ()
#2 0x9ffa1ebd in prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) ()
#3 0x9ff9f858 in _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) ()
#4 0x9ff9f779 in _FSURLCopyResourcePropertyForKey ()
#5 0x93765cd0 in CFURLCopyResourcePropertyForKey ()
#6 0x937dfaf6 in _VolumeObserverDiskAppearedCallback ()
#7 0x9513f6ab in _DADispatchCallback ()
#8 0x9513f439 in _DASessionCallback ()
#9 0x9513f304 in __DASessionSetDispatchQueue_block_invoke_2 ()
#10 0x0030e94d in _dispatch_client_callout ()
#11 0x00323464 in _dispatch_continuation_pop ()
#12 0x00310eba in _dispatch_source_invoke ()
#13 0x00324b73 in _dispatch_queue_serial_drain ()
#14 0x003162e2 in _dispatch_queue_invoke ()
#15 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#16 0x0032b4bb in _dispatch_workloop_worker_thread ()
#17 0x00381601 in _pthread_wqthread ()
#18 0x0038121e in start_wqthread ()

Re: Canceling NSSavePanel Hang App

Sandor Szatmari
 

Thanks Sak,

My discovery seemed random and unsettling, so I kept digging.  I will read the docs you’re referring to But a sheet does seem to do the trick.  What’s weird is this code has worked for years, so it must be some changes to the SDK I am updating to.


Sandor

On Apr 2, 2020, at 14:31, Sak Wathanasin <sw@...> wrote:



On 2 Apr 2020, at 18:54, Sandor Szatmari <admin.szatmari.net@...> wrote:

Took a guess and enabled sandbox and added read/write to user selected file and the hang went away.  Is it true that I cannot make an unsandboxed app and uses the NSSavePanel?  I know this is a data point of one, so I want to be careful what conclusions I draw… any thoughts?

No, I have a non-sandboxed app and it works fine. I think the problem is that you are using NSSavePanel:runModal. If you look in the doc'n, it says:

"This method invokes NSApplication's runModalForWindow ..."

If it's doing that, then you need to cancel the modal yourslef (as with any call of runModalForWindow). Try putting a

[NSApp stopModalWithCode:NSModalResponseCancel];

in your "else" clause.

However, it may be simpler to use a sheet modal:
...setup code...
    [panel beginSheetModalForWindow:owningWindow
                  completionHandler:^(NSInteger result){
                      if (result == NSFileHandlingPanelOKButton)
                      {
                          self.saveFileURL = [[panel URLs] objectAtIndex:0];
                          [self writeToFileAtURL:self.saveFileURL];
                      }
                  }
     ];

You can spin the writing to a file off to a separate thread if it takes a long time.

Hope this helps,

Sak


Re: Canceling NSSavePanel Hang App

Sak Wathanasin
 



On 2 Apr 2020, at 18:54, Sandor Szatmari <admin.szatmari.net@...> wrote:

Took a guess and enabled sandbox and added read/write to user selected file and the hang went away.  Is it true that I cannot make an unsandboxed app and uses the NSSavePanel?  I know this is a data point of one, so I want to be careful what conclusions I draw… any thoughts?

No, I have a non-sandboxed app and it works fine. I think the problem is that you are using NSSavePanel:runModal. If you look in the doc'n, it says:

"This method invokes NSApplication's runModalForWindow ..."

If it's doing that, then you need to cancel the modal yourslef (as with any call of runModalForWindow). Try putting a

[NSApp stopModalWithCode:NSModalResponseCancel];

in your "else" clause.

However, it may be simpler to use a sheet modal:
...setup code...
    [panel beginSheetModalForWindow:owningWindow
                  completionHandler:^(NSInteger result){
                      if (result == NSFileHandlingPanelOKButton)
                      {
                          self.saveFileURL = [[panel URLs] objectAtIndex:0];
                          [self writeToFileAtURL:self.saveFileURL];
                      }
                  }
     ];

You can spin the writing to a file off to a separate thread if it takes a long time.

Hope this helps,

Sak


Re: Canceling NSSavePanel Hang App

Sandor Szatmari
 

Already reading app sandbox design guide, was hoping for pointers to other apple resources, videos, etc…

Thanks,
Sandor

On Apr 2, 2020, at 13:54, Sandor Szatmari via groups.io <admin.szatmari.net=gmail.com@groups.io> wrote:

Took a guess and enabled sandbox and added read/write to user selected file and the hang went away. Is it true that I cannot make an unsandboxed app and uses the NSSavePanel? I know this is a data point of one, so I want to be careful what conclusions I draw… any thoughts?

Can anyone shed light/point me in the right direction as to where to update my knowledge?

Sandor

On Apr 1, 2020, at 17:31, Sandor Szatmari via groups.io <admin.szatmari.net=gmail.com@groups.io> wrote:

Ran into an interesting issue today…
Mac app
Xcode 9.4.1, 32bit, 10.12 SDK, 10.6 Deployment Target
non-sandboxed app

I am opening an NSSavePanel to allow a user to save the results of a report that is to be generated.

// Creating the save panel
NSSavePanel* savePanel = [NSSavePanel savePanel];
[savePanel setTitle:[NSString stringWithFormat:@"Export %@ Summary Data for %@", [self selectedReport], customerName]];

Opening the NSSavePanel using -runModal
savePanelUserAction = [savePanel runModal];

If the user enters a filename and clicks continue the save dialog closes, the report is generated, and the file is written to disk at the selected location.
if (savePanelUserAction == NSFileHandlingPanelOKButton)
[NSThread detachNewThreadSelector:@selector(createSummary:) toTarget:self withObject:[[savePanel URL] path]];

If the user clicks cancel, the program hangs. It hangs so badly that I have to go to the System Force-Quit dialog in order to fully terminate the app.
(i.e. Clicking stop program in Xcode does not fully terminate the app)
else
{
// Program hangs
}

I have checked that the NSSavePanel is being opened from the main thread.
I have included interesting backtraces below that are present if I stop the app in the de

Sandor

Thread 1 Queue : com.apple.main-thread (serial)
#0 0xa73d423e in kevent_id ()
#1 0x003305a6 in _dispatch_kq_poll ()
#2 0x00331141 in _dispatch_event_loop_wait_for_ownership ()
#3 0x00327b80 in _dispatch_sync_wait ()
#4 0x0031d500 in _dispatch_sync_f_slow ()
#5 0x0030f6d1 in dispatch_barrier_sync_f ()
#6 0x00316bf3 in dispatch_barrier_sync ()
#7 0x9387ebd4 in _VolumeObserverInvalidate ()
#8 0xa04ee78e in TSystemNotificationTask::~TSystemNotificationTask() ()
#9 0xa04ee818 in TSystemNotificationTask::FinalizeSystemNotificationTask() ()
#10 0xa04dda71 in NodeContextClose ()
#11 0x0afc689a in TFENode::Finalize() ()
#12 0x0b127290 in +[FIFinderViewGutsController finalizeCounted] ()
#13 0x0b127366 in __45+[FIFinderViewGutsController finalizeCounted]_block_invoke ()
#14 0x003167af in _dispatch_call_block_and_release ()
#15 0x0030e94d in _dispatch_client_callout ()
#16 0x0031ae6c in _dispatch_main_queue_callback_4CF ()
#17 0x937bb2ae in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#18 0x9377ecf4 in __CFRunLoopRun ()
#19 0x9377dbd1 in CFRunLoopRunSpecific ()
#20 0x9377d93a in CFRunLoopRunInMode ()
#21 0x92d7b37b in RunCurrentEventLoopInMode ()
#22 0x92d7b0a2 in ReceiveNextEventCommon ()
#23 0x92d7ad7b in _BlockUntilNextEventMatchingListInModeWithFilter ()
#24 0x9137aafd in _DPSNextEvent ()
#25 0x91aece90 in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] ()
#26 0x91aec35d in -[NSApplication(NSEvent) nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#27 0x9136fa4d in -[NSApplication run] ()
#28 0x91341b0a in NSApplicationMain ()
#29 0x000026bc in main at /Users/username/repo/AppName/main.m:13
#30 0x00002685 in start ()
Enqueued from TBrowserViewDataSource (Thread 14) Queue : TBrowserViewDataSource (serial)
#0 0x0033f4dc in _dispatch_introspection_queue_item_enqueue ()
#1 0x00325cf8 in _dispatch_queue_push ()
#2 0x00323230 in _dispatch_continuation_push ()
#3 0x0032259b in _dispatch_continuation_async ()
#4 0x00316173 in dispatch_async ()
#5 0x0b1272f6 in +[FIFinderViewGutsController finalizeCounted] ()
#6 0x0b1aa3af in -[FI_TBrowserViewDataSource dealloc] ()
#7 0xa67a09f9 in objc_object::sidetable_release(bool) ()
#8 0xa679e2d0 in -[NSObject release] ()
#9 0x0b1aa762 in __destroy_helper_block_ ()
#10 0xa72c6b75 in _Block_release ()
#11 0x0030e94d in _dispatch_client_callout ()
#12 0x00324d3a in _dispatch_queue_serial_drain ()
#13 0x003162e2 in _dispatch_queue_invoke ()
#14 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#15 0x0032b4bb in _dispatch_workloop_worker_thread ()
#16 0x00381601 in _pthread_wqthread ()
#17 0x0038121e in start_wqthread ()
Enqueued from com.apple.main-thread (Thread 1) Queue : com.apple.main-thread (serial)
#0 0x0033f4dc in _dispatch_introspection_queue_item_enqueue ()
#1 0x00325cf8 in _dispatch_queue_push ()
#2 0x00323230 in _dispatch_continuation_push ()
#3 0x0032259b in _dispatch_continuation_async ()
#4 0x00316173 in dispatch_async ()
#5 0x0b1aa460 in -[FI_TBrowserViewDataSource aboutToTearDown] ()
#6 0x0b1e0aa5 in -[FI_TBrowserContainerController destroyBrowserView:] ()
#7 0x0b1e3ed4 in -[FIContainerController destroyBrowserView:] ()
#8 0x0b1e06c6 in -[FI_TBrowserContainerController aboutToTearDown] ()
#9 0x0b1e3f3b in -[FIContainerController aboutToTearDown] ()
#10 0xa67a0bda in -[NSObject performSelector:] ()
#11 0x0b042f47 in AboutToTearDownViewController(NSViewController*) ()
#12 0x0b07a83c in -[FI_TBrowserContentViewController aboutToTearDown] ()
#13 0xa67a0bda in -[NSObject performSelector:] ()
#14 0x0b042f47 in AboutToTearDownViewController(NSViewController*) ()
#15 0x0b1293f0 in -[FIFinderViewGutsController prepareToHide] ()
#16 0x0b12996f in -[FIFinderViewGutsController windowOrderedOut] ()
#17 0x0b13486f in -[FIFinderView windowOrderedOut] ()
#18 0x91e3ffe5 in -[NSNavFinderViewFileBrowser windowOrderedOut] ()
#19 0x91a4df5e in -[NSSavePanel _navViewWindowOrderedOut] ()
#20 0x91a4dfc5 in -[NSSavePanel orderOut:] ()
#21 0x91a5bffa in -[NSSavePanel _didEndSheet:returnCode:contextInfo:] ()
#22 0x91c27b17 in NSWindowEndWindowModalSession ()
#23 0x915acaf6 in -[NSWindow _endWindowBlockingModalSession:returnCode:] ()
#24 0x915aca86 in -[NSWindow endSheet:returnCode:] ()
#25 0x915f7367 in -[NSApplication endSheet:returnCode:] ()
#26 0x91a5e2cb in -[NSSavePanel _dismissWindowWithReturnCode:willRunSeamlessOpening:] ()
#27 0x91a5e2f1 in -[NSSavePanel _cancelAndClose] ()
#28 0x91a5e933 in -[NSSavePanel cancel:] ()
#29 0xa67a0c1c in -[NSObject performSelector:withObject:] ()
#30 0x91aeeca9 in __49-[NSApplication(NSResponder) sendAction:to:from:]_block_invoke ()
#31 0x91aeec4d in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#32 0x91aeeb4f in -[NSApplication(NSResponder) sendAction:to:from:] ()
#33 0x9159eda8 in -[NSControl sendAction:to:] ()
#34 0x9159ecc7 in __26-[NSCell _sendActionFrom:]_block_invoke ()
#35 0x917e5009 in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#36 0x9159ec11 in -[NSCell _sendActionFrom:] ()
#37 0x915dd6cb in -[NSButtonCell _sendActionFrom:] ()
#38 0x917e6e2c in __48-[NSCell trackMouse:inRect:ofView:untilMouseUp:]_block_invoke.1099 ()
#39 0x917e5009 in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#40 0x9159d58d in -[NSCell trackMouse:inRect:ofView:untilMouseUp:] ()
#41 0x915dd420 in -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] ()
#42 0x9159bff4 in -[NSControl mouseDown:] ()
#43 0x91c922b4 in -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] ()
#44 0x91c9024f in -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] ()
#45 0x91c8e4c0 in -[NSWindow(NSEventRouting) sendEvent:] ()
#46 0x91aeb2d5 in -[NSApplication(NSEvent) sendEvent:] ()
#47 0x9136fa98 in -[NSApplication run] ()
#48 0x91341b0a in NSApplicationMain ()
#49 0x000026bc in main at /Users/username/repo/AppName/main.m:13
#50 0x00002685 in start ()


// Other threads that seemed interesting, but could be misleading???

Thread 2 Queue : com.apple.CFVolumeObserver.0x6af670 (serial)
#0 0xa73d242a in __getattrlist ()
#1 0x9ffa770f in volumePropertyProviderPrepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) ()
#2 0x9ffa1ebd in prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) ()
#3 0x9ff9f858 in _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) ()
#4 0x9ff9f779 in _FSURLCopyResourcePropertyForKey ()
#5 0x93765cd0 in CFURLCopyResourcePropertyForKey ()
#6 0x937dfaf6 in _VolumeObserverDiskAppearedCallback ()
#7 0x9513f6ab in _DADispatchCallback ()
#8 0x9513f439 in _DASessionCallback ()
#9 0x9513f304 in __DASessionSetDispatchQueue_block_invoke_2 ()
#10 0x0030e94d in _dispatch_client_callout ()
#11 0x00323464 in _dispatch_continuation_pop ()
#12 0x00310eba in _dispatch_source_invoke ()
#13 0x00324b73 in _dispatch_queue_serial_drain ()
#14 0x003162e2 in _dispatch_queue_invoke ()
#15 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#16 0x0032b4bb in _dispatch_workloop_worker_thread ()
#17 0x00381601 in _pthread_wqthread ()
#18 0x0038121e in start_wqthread ()


Thread 10 Queue : com.apple.CFVolumeObserver.0x6ac5d0 (serial)
#0 0xa73d242a in __getattrlist ()
#1 0x9ffa770f in volumePropertyProviderPrepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) ()
#2 0x9ffa1ebd in prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) ()
#3 0x9ff9f858 in _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) ()
#4 0x9ff9f779 in _FSURLCopyResourcePropertyForKey ()
#5 0x93765cd0 in CFURLCopyResourcePropertyForKey ()
#6 0x937dfaf6 in _VolumeObserverDiskAppearedCallback ()
#7 0x9513f6ab in _DADispatchCallback ()
#8 0x9513f439 in _DASessionCallback ()
#9 0x9513f304 in __DASessionSetDispatchQueue_block_invoke_2 ()
#10 0x0030e94d in _dispatch_client_callout ()
#11 0x00323464 in _dispatch_continuation_pop ()
#12 0x00310eba in _dispatch_source_invoke ()
#13 0x00324b73 in _dispatch_queue_serial_drain ()
#14 0x003162e2 in _dispatch_queue_invoke ()
#15 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#16 0x0032b4bb in _dispatch_workloop_worker_thread ()
#17 0x00381601 in _pthread_wqthread ()
#18 0x0038121e in start_wqthread ()


Re: Canceling NSSavePanel Hang App

Sandor Szatmari
 

Took a guess and enabled sandbox and added read/write to user selected file and the hang went away. Is it true that I cannot make an unsandboxed app and uses the NSSavePanel? I know this is a data point of one, so I want to be careful what conclusions I draw… any thoughts?

Can anyone shed light/point me in the right direction as to where to update my knowledge?

Sandor

On Apr 1, 2020, at 17:31, Sandor Szatmari via groups.io <admin.szatmari.net=gmail.com@groups.io> wrote:

Ran into an interesting issue today…
Mac app
Xcode 9.4.1, 32bit, 10.12 SDK, 10.6 Deployment Target
non-sandboxed app

I am opening an NSSavePanel to allow a user to save the results of a report that is to be generated.

// Creating the save panel
NSSavePanel* savePanel = [NSSavePanel savePanel];
[savePanel setTitle:[NSString stringWithFormat:@"Export %@ Summary Data for %@", [self selectedReport], customerName]];

Opening the NSSavePanel using -runModal
savePanelUserAction = [savePanel runModal];

If the user enters a filename and clicks continue the save dialog closes, the report is generated, and the file is written to disk at the selected location.
if (savePanelUserAction == NSFileHandlingPanelOKButton)
[NSThread detachNewThreadSelector:@selector(createSummary:) toTarget:self withObject:[[savePanel URL] path]];

If the user clicks cancel, the program hangs. It hangs so badly that I have to go to the System Force-Quit dialog in order to fully terminate the app.
(i.e. Clicking stop program in Xcode does not fully terminate the app)
else
{
// Program hangs
}

I have checked that the NSSavePanel is being opened from the main thread.
I have included interesting backtraces below that are present if I stop the app in the de

Sandor

Thread 1 Queue : com.apple.main-thread (serial)
#0 0xa73d423e in kevent_id ()
#1 0x003305a6 in _dispatch_kq_poll ()
#2 0x00331141 in _dispatch_event_loop_wait_for_ownership ()
#3 0x00327b80 in _dispatch_sync_wait ()
#4 0x0031d500 in _dispatch_sync_f_slow ()
#5 0x0030f6d1 in dispatch_barrier_sync_f ()
#6 0x00316bf3 in dispatch_barrier_sync ()
#7 0x9387ebd4 in _VolumeObserverInvalidate ()
#8 0xa04ee78e in TSystemNotificationTask::~TSystemNotificationTask() ()
#9 0xa04ee818 in TSystemNotificationTask::FinalizeSystemNotificationTask() ()
#10 0xa04dda71 in NodeContextClose ()
#11 0x0afc689a in TFENode::Finalize() ()
#12 0x0b127290 in +[FIFinderViewGutsController finalizeCounted] ()
#13 0x0b127366 in __45+[FIFinderViewGutsController finalizeCounted]_block_invoke ()
#14 0x003167af in _dispatch_call_block_and_release ()
#15 0x0030e94d in _dispatch_client_callout ()
#16 0x0031ae6c in _dispatch_main_queue_callback_4CF ()
#17 0x937bb2ae in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#18 0x9377ecf4 in __CFRunLoopRun ()
#19 0x9377dbd1 in CFRunLoopRunSpecific ()
#20 0x9377d93a in CFRunLoopRunInMode ()
#21 0x92d7b37b in RunCurrentEventLoopInMode ()
#22 0x92d7b0a2 in ReceiveNextEventCommon ()
#23 0x92d7ad7b in _BlockUntilNextEventMatchingListInModeWithFilter ()
#24 0x9137aafd in _DPSNextEvent ()
#25 0x91aece90 in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] ()
#26 0x91aec35d in -[NSApplication(NSEvent) nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#27 0x9136fa4d in -[NSApplication run] ()
#28 0x91341b0a in NSApplicationMain ()
#29 0x000026bc in main at /Users/username/repo/AppName/main.m:13
#30 0x00002685 in start ()
Enqueued from TBrowserViewDataSource (Thread 14) Queue : TBrowserViewDataSource (serial)
#0 0x0033f4dc in _dispatch_introspection_queue_item_enqueue ()
#1 0x00325cf8 in _dispatch_queue_push ()
#2 0x00323230 in _dispatch_continuation_push ()
#3 0x0032259b in _dispatch_continuation_async ()
#4 0x00316173 in dispatch_async ()
#5 0x0b1272f6 in +[FIFinderViewGutsController finalizeCounted] ()
#6 0x0b1aa3af in -[FI_TBrowserViewDataSource dealloc] ()
#7 0xa67a09f9 in objc_object::sidetable_release(bool) ()
#8 0xa679e2d0 in -[NSObject release] ()
#9 0x0b1aa762 in __destroy_helper_block_ ()
#10 0xa72c6b75 in _Block_release ()
#11 0x0030e94d in _dispatch_client_callout ()
#12 0x00324d3a in _dispatch_queue_serial_drain ()
#13 0x003162e2 in _dispatch_queue_invoke ()
#14 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#15 0x0032b4bb in _dispatch_workloop_worker_thread ()
#16 0x00381601 in _pthread_wqthread ()
#17 0x0038121e in start_wqthread ()
Enqueued from com.apple.main-thread (Thread 1) Queue : com.apple.main-thread (serial)
#0 0x0033f4dc in _dispatch_introspection_queue_item_enqueue ()
#1 0x00325cf8 in _dispatch_queue_push ()
#2 0x00323230 in _dispatch_continuation_push ()
#3 0x0032259b in _dispatch_continuation_async ()
#4 0x00316173 in dispatch_async ()
#5 0x0b1aa460 in -[FI_TBrowserViewDataSource aboutToTearDown] ()
#6 0x0b1e0aa5 in -[FI_TBrowserContainerController destroyBrowserView:] ()
#7 0x0b1e3ed4 in -[FIContainerController destroyBrowserView:] ()
#8 0x0b1e06c6 in -[FI_TBrowserContainerController aboutToTearDown] ()
#9 0x0b1e3f3b in -[FIContainerController aboutToTearDown] ()
#10 0xa67a0bda in -[NSObject performSelector:] ()
#11 0x0b042f47 in AboutToTearDownViewController(NSViewController*) ()
#12 0x0b07a83c in -[FI_TBrowserContentViewController aboutToTearDown] ()
#13 0xa67a0bda in -[NSObject performSelector:] ()
#14 0x0b042f47 in AboutToTearDownViewController(NSViewController*) ()
#15 0x0b1293f0 in -[FIFinderViewGutsController prepareToHide] ()
#16 0x0b12996f in -[FIFinderViewGutsController windowOrderedOut] ()
#17 0x0b13486f in -[FIFinderView windowOrderedOut] ()
#18 0x91e3ffe5 in -[NSNavFinderViewFileBrowser windowOrderedOut] ()
#19 0x91a4df5e in -[NSSavePanel _navViewWindowOrderedOut] ()
#20 0x91a4dfc5 in -[NSSavePanel orderOut:] ()
#21 0x91a5bffa in -[NSSavePanel _didEndSheet:returnCode:contextInfo:] ()
#22 0x91c27b17 in NSWindowEndWindowModalSession ()
#23 0x915acaf6 in -[NSWindow _endWindowBlockingModalSession:returnCode:] ()
#24 0x915aca86 in -[NSWindow endSheet:returnCode:] ()
#25 0x915f7367 in -[NSApplication endSheet:returnCode:] ()
#26 0x91a5e2cb in -[NSSavePanel _dismissWindowWithReturnCode:willRunSeamlessOpening:] ()
#27 0x91a5e2f1 in -[NSSavePanel _cancelAndClose] ()
#28 0x91a5e933 in -[NSSavePanel cancel:] ()
#29 0xa67a0c1c in -[NSObject performSelector:withObject:] ()
#30 0x91aeeca9 in __49-[NSApplication(NSResponder) sendAction:to:from:]_block_invoke ()
#31 0x91aeec4d in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#32 0x91aeeb4f in -[NSApplication(NSResponder) sendAction:to:from:] ()
#33 0x9159eda8 in -[NSControl sendAction:to:] ()
#34 0x9159ecc7 in __26-[NSCell _sendActionFrom:]_block_invoke ()
#35 0x917e5009 in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#36 0x9159ec11 in -[NSCell _sendActionFrom:] ()
#37 0x915dd6cb in -[NSButtonCell _sendActionFrom:] ()
#38 0x917e6e2c in __48-[NSCell trackMouse:inRect:ofView:untilMouseUp:]_block_invoke.1099 ()
#39 0x917e5009 in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#40 0x9159d58d in -[NSCell trackMouse:inRect:ofView:untilMouseUp:] ()
#41 0x915dd420 in -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] ()
#42 0x9159bff4 in -[NSControl mouseDown:] ()
#43 0x91c922b4 in -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] ()
#44 0x91c9024f in -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] ()
#45 0x91c8e4c0 in -[NSWindow(NSEventRouting) sendEvent:] ()
#46 0x91aeb2d5 in -[NSApplication(NSEvent) sendEvent:] ()
#47 0x9136fa98 in -[NSApplication run] ()
#48 0x91341b0a in NSApplicationMain ()
#49 0x000026bc in main at /Users/username/repo/AppName/main.m:13
#50 0x00002685 in start ()


// Other threads that seemed interesting, but could be misleading???

Thread 2 Queue : com.apple.CFVolumeObserver.0x6af670 (serial)
#0 0xa73d242a in __getattrlist ()
#1 0x9ffa770f in volumePropertyProviderPrepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) ()
#2 0x9ffa1ebd in prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) ()
#3 0x9ff9f858 in _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) ()
#4 0x9ff9f779 in _FSURLCopyResourcePropertyForKey ()
#5 0x93765cd0 in CFURLCopyResourcePropertyForKey ()
#6 0x937dfaf6 in _VolumeObserverDiskAppearedCallback ()
#7 0x9513f6ab in _DADispatchCallback ()
#8 0x9513f439 in _DASessionCallback ()
#9 0x9513f304 in __DASessionSetDispatchQueue_block_invoke_2 ()
#10 0x0030e94d in _dispatch_client_callout ()
#11 0x00323464 in _dispatch_continuation_pop ()
#12 0x00310eba in _dispatch_source_invoke ()
#13 0x00324b73 in _dispatch_queue_serial_drain ()
#14 0x003162e2 in _dispatch_queue_invoke ()
#15 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#16 0x0032b4bb in _dispatch_workloop_worker_thread ()
#17 0x00381601 in _pthread_wqthread ()
#18 0x0038121e in start_wqthread ()


Thread 10 Queue : com.apple.CFVolumeObserver.0x6ac5d0 (serial)
#0 0xa73d242a in __getattrlist ()
#1 0x9ffa770f in volumePropertyProviderPrepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) ()
#2 0x9ffa1ebd in prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) ()
#3 0x9ff9f858 in _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) ()
#4 0x9ff9f779 in _FSURLCopyResourcePropertyForKey ()
#5 0x93765cd0 in CFURLCopyResourcePropertyForKey ()
#6 0x937dfaf6 in _VolumeObserverDiskAppearedCallback ()
#7 0x9513f6ab in _DADispatchCallback ()
#8 0x9513f439 in _DASessionCallback ()
#9 0x9513f304 in __DASessionSetDispatchQueue_block_invoke_2 ()
#10 0x0030e94d in _dispatch_client_callout ()
#11 0x00323464 in _dispatch_continuation_pop ()
#12 0x00310eba in _dispatch_source_invoke ()
#13 0x00324b73 in _dispatch_queue_serial_drain ()
#14 0x003162e2 in _dispatch_queue_invoke ()
#15 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#16 0x0032b4bb in _dispatch_workloop_worker_thread ()
#17 0x00381601 in _pthread_wqthread ()
#18 0x0038121e in start_wqthread ()

Canceling NSSavePanel Hang App

Sandor Szatmari
 

Ran into an interesting issue today…
Mac app
Xcode 9.4.1, 32bit, 10.12 SDK, 10.6 Deployment Target
non-sandboxed app

I am opening an NSSavePanel to allow a user to save the results of a report that is to be generated.

// Creating the save panel
NSSavePanel* savePanel = [NSSavePanel savePanel];
[savePanel setTitle:[NSString stringWithFormat:@"Export %@ Summary Data for %@", [self selectedReport], customerName]];

Opening the NSSavePanel using -runModal
savePanelUserAction = [savePanel runModal];

If the user enters a filename and clicks continue the save dialog closes, the report is generated, and the file is written to disk at the selected location.
if (savePanelUserAction == NSFileHandlingPanelOKButton)
[NSThread detachNewThreadSelector:@selector(createSummary:) toTarget:self withObject:[[savePanel URL] path]];

If the user clicks cancel, the program hangs. It hangs so badly that I have to go to the System Force-Quit dialog in order to fully terminate the app.
(i.e. Clicking stop program in Xcode does not fully terminate the app)
else
{
// Program hangs
}

I have checked that the NSSavePanel is being opened from the main thread.
I have included interesting backtraces below that are present if I stop the app in the de

Sandor

Thread 1 Queue : com.apple.main-thread (serial)
#0 0xa73d423e in kevent_id ()
#1 0x003305a6 in _dispatch_kq_poll ()
#2 0x00331141 in _dispatch_event_loop_wait_for_ownership ()
#3 0x00327b80 in _dispatch_sync_wait ()
#4 0x0031d500 in _dispatch_sync_f_slow ()
#5 0x0030f6d1 in dispatch_barrier_sync_f ()
#6 0x00316bf3 in dispatch_barrier_sync ()
#7 0x9387ebd4 in _VolumeObserverInvalidate ()
#8 0xa04ee78e in TSystemNotificationTask::~TSystemNotificationTask() ()
#9 0xa04ee818 in TSystemNotificationTask::FinalizeSystemNotificationTask() ()
#10 0xa04dda71 in NodeContextClose ()
#11 0x0afc689a in TFENode::Finalize() ()
#12 0x0b127290 in +[FIFinderViewGutsController finalizeCounted] ()
#13 0x0b127366 in __45+[FIFinderViewGutsController finalizeCounted]_block_invoke ()
#14 0x003167af in _dispatch_call_block_and_release ()
#15 0x0030e94d in _dispatch_client_callout ()
#16 0x0031ae6c in _dispatch_main_queue_callback_4CF ()
#17 0x937bb2ae in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#18 0x9377ecf4 in __CFRunLoopRun ()
#19 0x9377dbd1 in CFRunLoopRunSpecific ()
#20 0x9377d93a in CFRunLoopRunInMode ()
#21 0x92d7b37b in RunCurrentEventLoopInMode ()
#22 0x92d7b0a2 in ReceiveNextEventCommon ()
#23 0x92d7ad7b in _BlockUntilNextEventMatchingListInModeWithFilter ()
#24 0x9137aafd in _DPSNextEvent ()
#25 0x91aece90 in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] ()
#26 0x91aec35d in -[NSApplication(NSEvent) nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#27 0x9136fa4d in -[NSApplication run] ()
#28 0x91341b0a in NSApplicationMain ()
#29 0x000026bc in main at /Users/username/repo/AppName/main.m:13
#30 0x00002685 in start ()
Enqueued from TBrowserViewDataSource (Thread 14) Queue : TBrowserViewDataSource (serial)
#0 0x0033f4dc in _dispatch_introspection_queue_item_enqueue ()
#1 0x00325cf8 in _dispatch_queue_push ()
#2 0x00323230 in _dispatch_continuation_push ()
#3 0x0032259b in _dispatch_continuation_async ()
#4 0x00316173 in dispatch_async ()
#5 0x0b1272f6 in +[FIFinderViewGutsController finalizeCounted] ()
#6 0x0b1aa3af in -[FI_TBrowserViewDataSource dealloc] ()
#7 0xa67a09f9 in objc_object::sidetable_release(bool) ()
#8 0xa679e2d0 in -[NSObject release] ()
#9 0x0b1aa762 in __destroy_helper_block_ ()
#10 0xa72c6b75 in _Block_release ()
#11 0x0030e94d in _dispatch_client_callout ()
#12 0x00324d3a in _dispatch_queue_serial_drain ()
#13 0x003162e2 in _dispatch_queue_invoke ()
#14 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#15 0x0032b4bb in _dispatch_workloop_worker_thread ()
#16 0x00381601 in _pthread_wqthread ()
#17 0x0038121e in start_wqthread ()
Enqueued from com.apple.main-thread (Thread 1) Queue : com.apple.main-thread (serial)
#0 0x0033f4dc in _dispatch_introspection_queue_item_enqueue ()
#1 0x00325cf8 in _dispatch_queue_push ()
#2 0x00323230 in _dispatch_continuation_push ()
#3 0x0032259b in _dispatch_continuation_async ()
#4 0x00316173 in dispatch_async ()
#5 0x0b1aa460 in -[FI_TBrowserViewDataSource aboutToTearDown] ()
#6 0x0b1e0aa5 in -[FI_TBrowserContainerController destroyBrowserView:] ()
#7 0x0b1e3ed4 in -[FIContainerController destroyBrowserView:] ()
#8 0x0b1e06c6 in -[FI_TBrowserContainerController aboutToTearDown] ()
#9 0x0b1e3f3b in -[FIContainerController aboutToTearDown] ()
#10 0xa67a0bda in -[NSObject performSelector:] ()
#11 0x0b042f47 in AboutToTearDownViewController(NSViewController*) ()
#12 0x0b07a83c in -[FI_TBrowserContentViewController aboutToTearDown] ()
#13 0xa67a0bda in -[NSObject performSelector:] ()
#14 0x0b042f47 in AboutToTearDownViewController(NSViewController*) ()
#15 0x0b1293f0 in -[FIFinderViewGutsController prepareToHide] ()
#16 0x0b12996f in -[FIFinderViewGutsController windowOrderedOut] ()
#17 0x0b13486f in -[FIFinderView windowOrderedOut] ()
#18 0x91e3ffe5 in -[NSNavFinderViewFileBrowser windowOrderedOut] ()
#19 0x91a4df5e in -[NSSavePanel _navViewWindowOrderedOut] ()
#20 0x91a4dfc5 in -[NSSavePanel orderOut:] ()
#21 0x91a5bffa in -[NSSavePanel _didEndSheet:returnCode:contextInfo:] ()
#22 0x91c27b17 in NSWindowEndWindowModalSession ()
#23 0x915acaf6 in -[NSWindow _endWindowBlockingModalSession:returnCode:] ()
#24 0x915aca86 in -[NSWindow endSheet:returnCode:] ()
#25 0x915f7367 in -[NSApplication endSheet:returnCode:] ()
#26 0x91a5e2cb in -[NSSavePanel _dismissWindowWithReturnCode:willRunSeamlessOpening:] ()
#27 0x91a5e2f1 in -[NSSavePanel _cancelAndClose] ()
#28 0x91a5e933 in -[NSSavePanel cancel:] ()
#29 0xa67a0c1c in -[NSObject performSelector:withObject:] ()
#30 0x91aeeca9 in __49-[NSApplication(NSResponder) sendAction:to:from:]_block_invoke ()
#31 0x91aeec4d in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#32 0x91aeeb4f in -[NSApplication(NSResponder) sendAction:to:from:] ()
#33 0x9159eda8 in -[NSControl sendAction:to:] ()
#34 0x9159ecc7 in __26-[NSCell _sendActionFrom:]_block_invoke ()
#35 0x917e5009 in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#36 0x9159ec11 in -[NSCell _sendActionFrom:] ()
#37 0x915dd6cb in -[NSButtonCell _sendActionFrom:] ()
#38 0x917e6e2c in __48-[NSCell trackMouse:inRect:ofView:untilMouseUp:]_block_invoke.1099 ()
#39 0x917e5009 in __NS_ACTIVITY_PERFORM_EXCEPTION_SAFE ()
#40 0x9159d58d in -[NSCell trackMouse:inRect:ofView:untilMouseUp:] ()
#41 0x915dd420 in -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] ()
#42 0x9159bff4 in -[NSControl mouseDown:] ()
#43 0x91c922b4 in -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] ()
#44 0x91c9024f in -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] ()
#45 0x91c8e4c0 in -[NSWindow(NSEventRouting) sendEvent:] ()
#46 0x91aeb2d5 in -[NSApplication(NSEvent) sendEvent:] ()
#47 0x9136fa98 in -[NSApplication run] ()
#48 0x91341b0a in NSApplicationMain ()
#49 0x000026bc in main at /Users/username/repo/AppName/main.m:13
#50 0x00002685 in start ()


// Other threads that seemed interesting, but could be misleading???

Thread 2 Queue : com.apple.CFVolumeObserver.0x6af670 (serial)
#0 0xa73d242a in __getattrlist ()
#1 0x9ffa770f in volumePropertyProviderPrepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) ()
#2 0x9ffa1ebd in prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) ()
#3 0x9ff9f858 in _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) ()
#4 0x9ff9f779 in _FSURLCopyResourcePropertyForKey ()
#5 0x93765cd0 in CFURLCopyResourcePropertyForKey ()
#6 0x937dfaf6 in _VolumeObserverDiskAppearedCallback ()
#7 0x9513f6ab in _DADispatchCallback ()
#8 0x9513f439 in _DASessionCallback ()
#9 0x9513f304 in __DASessionSetDispatchQueue_block_invoke_2 ()
#10 0x0030e94d in _dispatch_client_callout ()
#11 0x00323464 in _dispatch_continuation_pop ()
#12 0x00310eba in _dispatch_source_invoke ()
#13 0x00324b73 in _dispatch_queue_serial_drain ()
#14 0x003162e2 in _dispatch_queue_invoke ()
#15 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#16 0x0032b4bb in _dispatch_workloop_worker_thread ()
#17 0x00381601 in _pthread_wqthread ()
#18 0x0038121e in start_wqthread ()


Thread 10 Queue : com.apple.CFVolumeObserver.0x6ac5d0 (serial)
#0 0xa73d242a in __getattrlist ()
#1 0x9ffa770f in volumePropertyProviderPrepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) ()
#2 0x9ffa1ebd in prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) ()
#3 0x9ff9f858 in _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) ()
#4 0x9ff9f779 in _FSURLCopyResourcePropertyForKey ()
#5 0x93765cd0 in CFURLCopyResourcePropertyForKey ()
#6 0x937dfaf6 in _VolumeObserverDiskAppearedCallback ()
#7 0x9513f6ab in _DADispatchCallback ()
#8 0x9513f439 in _DASessionCallback ()
#9 0x9513f304 in __DASessionSetDispatchQueue_block_invoke_2 ()
#10 0x0030e94d in _dispatch_client_callout ()
#11 0x00323464 in _dispatch_continuation_pop ()
#12 0x00310eba in _dispatch_source_invoke ()
#13 0x00324b73 in _dispatch_queue_serial_drain ()
#14 0x003162e2 in _dispatch_queue_invoke ()
#15 0x0032646e in _dispatch_root_queue_drain_deferred_wlh ()
#16 0x0032b4bb in _dispatch_workloop_worker_thread ()
#17 0x00381601 in _pthread_wqthread ()
#18 0x0038121e in start_wqthread ()

Re: Drawing to a PDF context

Sandor Szatmari
 

Jim,

On Mar 4, 2020, at 11:56 AM, Jim <jimcfl@...> wrote:


On Mar 4, 2020, at 11:06 AM, Quincey Morris <quinceymorris@...> wrote:

On Mar 4, 2020, at 06:52 , Sandor Szatmari <admin.szatmari.net@...> wrote:

I need to replace calls to CGShowTextAtPoint() with calls to -drawAtPoint:withAttributes:

I made this change and drawing fails… :/
i.e. no text rendered, no exception, logging of errors, etc. simply no text
Well, by default, NWView coordinates are flipped vs. CGContext coordinates. I suggest you try temporarily forcing the point you’re drawing at to be the center of the context or view, and see if the text even appears. If so, you should be able to see what you need to do to transform the point at which you’re drawing (based on which direction the text is running, and whether it’s upside down).

Are you switching over to PDFKit? In that case, you’ll have to respect whatever coordinate system it uses. It looks like there’s some advice on that subject in the “Override the Draw Method and Add Your Custom Graphic” section of https://developer.apple.com/documentation/pdfkit/adding_custom_graphics_to_a_pdf.
When I wrote an app that added things to an existing PDF a couple years ago, I was able to use text and custom annotations to display elements on a document in a PDFView, but was unable to figure out how to use PDFKit to save the annotations into the document so that they would be visible with Preview or Acrobat. It appears that PDFKit is primarily oriented around on-screen display and markup of a PDF, not creating or modifying a PDF.

So to save the changes I had to redraw the existing document in a CGPDFContext and then draw the elements as images in that context as well. This turns each PDF page into an image, which wasn’t a problem in my case, but is usually not desirable.
Yea, we are printing and distributing the PDF so it’s important to retain the vector nature of the PDF. People need to be able to zoom in to read the finer details.

Thanks!

Jim Crate



Re: Drawing to a PDF context

Sandor Szatmari
 

Quincey,


On Mar 4, 2020, at 11:07 AM, Quincey Morris <quinceymorris@...> wrote:

On Mar 4, 2020, at 06:52 , Sandor Szatmari <admin.szatmari.net@...> wrote:

I need to replace calls to CGShowTextAtPoint() with calls to -drawAtPoint:withAttributes:

I made this change and drawing fails… :/ 
i.e. no text rendered, no exception, logging of errors, etc. simply no text

Well, by default, NWView coordinates are flipped vs. CGContext coordinates. I suggest you try temporarily forcing the point you’re drawing at to be the center of the context or view, and see if the text even appears. If so, you should be able to see what you need to do to transform the point at which you’re drawing (based on which direction the text is running, and whether it’s upside down).

I tried a couple tweaks of the drawing coordinates but I should investigate more.  

Also interesting. If I call [NSGraphics currentContext] before trying to set the context it returns nil.


Are you switching over to PDFKit? In that case, you’ll have to respect whatever coordinate system it uses.

Not switching to PDFKit.  Just updating deployment target SDK and dealing with deprecations.

Thank you!

It looks like there’s some advice on that subject in the “Override the Draw Method and Add Your Custom Graphic” section of https://developer.apple.com/documentation/pdfkit/adding_custom_graphics_to_a_pdf.

Re: Drawing to a PDF context

Jim
 

On Mar 4, 2020, at 11:06 AM, Quincey Morris <quinceymorris@...> wrote:

On Mar 4, 2020, at 06:52 , Sandor Szatmari <admin.szatmari.net@...> wrote:

I need to replace calls to CGShowTextAtPoint() with calls to -drawAtPoint:withAttributes:

I made this change and drawing fails… :/
i.e. no text rendered, no exception, logging of errors, etc. simply no text
Well, by default, NWView coordinates are flipped vs. CGContext coordinates. I suggest you try temporarily forcing the point you’re drawing at to be the center of the context or view, and see if the text even appears. If so, you should be able to see what you need to do to transform the point at which you’re drawing (based on which direction the text is running, and whether it’s upside down).

Are you switching over to PDFKit? In that case, you’ll have to respect whatever coordinate system it uses. It looks like there’s some advice on that subject in the “Override the Draw Method and Add Your Custom Graphic” section of https://developer.apple.com/documentation/pdfkit/adding_custom_graphics_to_a_pdf.
When I wrote an app that added things to an existing PDF a couple years ago, I was able to use text and custom annotations to display elements on a document in a PDFView, but was unable to figure out how to use PDFKit to save the annotations into the document so that they would be visible with Preview or Acrobat. It appears that PDFKit is primarily oriented around on-screen display and markup of a PDF, not creating or modifying a PDF.

So to save the changes I had to redraw the existing document in a CGPDFContext and then draw the elements as images in that context as well. This turns each PDF page into an image, which wasn’t a problem in my case, but is usually not desirable.

Jim Crate

Re: Drawing to a PDF context

Quincey Morris
 

On Mar 4, 2020, at 06:52 , Sandor Szatmari <admin.szatmari.net@...> wrote:

I need to replace calls to CGShowTextAtPoint() with calls to -drawAtPoint:withAttributes:

I made this change and drawing fails… :/ 
i.e. no text rendered, no exception, logging of errors, etc. simply no text

Well, by default, NWView coordinates are flipped vs. CGContext coordinates. I suggest you try temporarily forcing the point you’re drawing at to be the center of the context or view, and see if the text even appears. If so, you should be able to see what you need to do to transform the point at which you’re drawing (based on which direction the text is running, and whether it’s upside down).

Are you switching over to PDFKit? In that case, you’ll have to respect whatever coordinate system it uses. It looks like there’s some advice on that subject in the “Override the Draw Method and Add Your Custom Graphic” section of https://developer.apple.com/documentation/pdfkit/adding_custom_graphics_to_a_pdf.

Drawing to a PDF context

Sandor Szatmari
 

I need to replace calls to CGShowTextAtPoint() with calls to -drawAtPoint:withAttributes:

I made this change and drawing fails… :/
i.e. no text rendered, no exception, logging of errors, etc. simply no text
The CG implementation of this code has been working with no leaks, crashes, etc for at least 10+ years.

Original context is created as follows:
CGContextRef ctx;
ctx = CGPDFContextCreateWithURL(…)

I tried setting the current NS graphics context like so

[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:ctx flipped:NO]

… but this causes the app to crash.

Any thoughts? Is this an ownership issue? Should I be letting the NSGraphics side of things know not to dispose of the context…

Thanks in advance,
Sandor

Re: NSAlert boxes ...

Jon Gotow
 

Oh interesting - it looks like when you call [NSAlert beginSheetModalForWindow:completionHandler:], the alert gets retained by the parent window's attachedSheet property. So you're right, no issues there either. Now that you've brought it up, I have to say I've never worried about the alert being released too early in my code when I use beginSheetModalForWindow - I never gave it much thought because it just worked.

- Jon

On Feb 17, 2020, at 12:54 AM, Graham Cox <graham@...> wrote:

That is the case I’m talking about and no, it works fine even if you don’t “worry” about the lifecycle.

Just alloc + init + autorelease, then beginSheet…. it works, it has always worked since completion blocks were introduced.

It also works for the -runModal case also, you can autorelease prior to that call and that also doesn’t cause a lifecycle issue.

You can certainly “worry” about extending the lifecycle into the completion block if you want, except the unbalanced release will throw a compiler warning. That in itself shows how unnecessary it is to bother with.

TL;DR: Normal rules apply, stop overthinking this! Just because an NSAlert has some unusual asynchronous lifespan doesn’t mean it needs to be treated any differently from any other object you instantiate.

Re: NSAlert boxes ...

Graham Cox
 



On 17 Feb 2020, at 4:27 pm, Jon Gotow <gotow@...> wrote:

If you were to use [NSAlert beginSheetModalForWindow:completionHandler:], then you'd have to worry about lifecycle of the alert extending beyond the current function context.


That is the case I’m talking about and no, it works fine even if you don’t “worry” about the lifecycle.

Just alloc + init + autorelease, then beginSheet…. it works, it has always worked since completion blocks were introduced.

It also works for the -runModal case also, you can autorelease prior to that call and that also doesn’t cause a lifecycle issue.

You can certainly “worry” about extending the lifecycle into the completion block if you want, except the unbalanced release will throw a compiler warning. That in itself shows how unnecessary it is to bother with.

TL;DR: Normal rules apply, stop overthinking this! Just because an NSAlert has some unusual asynchronous lifespan doesn’t mean it needs to be treated any differently from any other object you instantiate.

—Graham




Re: NSAlert boxes ...

Jon Gotow
 

You're making this far more complicated than it is (talking about running the alert asynchronously, etc).

NSModalResponse choice = [alert runModal];

will run the alert synchronously. Note that it returns a result from this method call, meaning that the call blocks by running its own modal event loop in runModal and only returns after the user has clicked on a button. That means that your autorelease is fine - the scope of this alert is just within the current function, so it'll get cleaned up at the end of the current runloop invocation. That said, you can also just release it manually after you call runModal, like this:

NSAlert *alert = [[NSAlert alloc] init];

alert.messageText = @"Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];

NSModalResponse choice = [alert runModal];

[alert release];

If you were to use [NSAlert beginSheetModalForWindow:completionHandler:], then you'd have to worry about lifecycle of the alert extending beyond the current function context.

- Jon

On Feb 16, 2020, at 6:17 AM, Peter Hudson via Groups.Io <Peter.hudson=me.com@groups.io> wrote:

Hi There

I see from the docs that when you create an NSAlert that you should dispose of it yourself.
My code for creating a simple alert and using it looks like this :-


NSAlert *alert = [[[NSAlert alloc] init] autorelease];
alert.messageText = @:Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];

NSModalResponse choice = [alert runModal];

Etc …..

Is the use of an autorelease here O.K. ?

It certainly seems to work …..



Peter

Re: NSAlert boxes ...

Graham Cox
 



On 17 Feb 2020, at 12:22 pm, Sandor Szatmari <admin.szatmari.net@...> wrote:

The MRR rules are straight forward and deviating from them because the runloop may retain the alert is asking for trouble in my opinion.  There is no harm in taking ownership of the alert and releasing/autoreleasing it.  I would argue that doing so ensures that any changes in SDK/runtime behavior don’t adversely affect your product.  

Sandor


That’s exactly what I’m saying - you are taking ownership of it with alloc+init.

Then you release it or autorelease it within the scope of setting it up. Normal rules.

But the point is the alert is run asynchronously, so it has to survive long after the scope of where you instantiated and set it up. Long after the next autorelease drain in fact. But that is someone else's problem - the run-loop’s, I’m supposing.

The alternative is to try to take ownership of it until it is finally and completely dismissed, which requires an unbalanced release in the completion block. This not only flags a warning when you compile, but it’s simply unnecessary. Trying to overthink the ownership rules in this case leads to code that is not only complicated, but redundant. The designers of NSAlert have already taken its lifetime into consideraton, so YOUR ownership of it only lasts as long as it takes to instantiate it, set it up, and ask it to run modally.

Peter’s original code, where he autoreleases as part of alloc + init, works absolutely fine.

—Graham


Re: NSAlert boxes ...

Sandor Szatmari
 

The MRR rules are straight forward and deviating from them because the runloop may retain the alert is asking for trouble in my opinion.  There is no harm in taking ownership of the alert and releasing/autoreleasing it.  I would argue that doing so ensures that any changes in SDK/runtime behavior don’t adversely affect your product.  

Sandor

On Feb 16, 2020, at 19:26, Peter Hudson via Groups.Io <Peter.hudson@...> wrote:


Thanks Graham and Alex. 
I had reached the same sort of conclusions - but could not find any corroborative info anywhere ....
Peter 

On 16 Feb 2020, at 23:59, Graham Cox <graham@...> wrote:

Normal rules require that you either autorelease it or release it when you’re done (assuming manual MM of course).

If no autorelease or release was required, then that would be an exception to normal rules, and NSAlert is not documented as an exception to those rules. However, the alert can stay on screen for a long time, and the event loop is running, albeit modally. That means that autorelease pools are getting drained. So *something* must be keeping the alert alive until the user dismisses it.

—Graham



On 17 Feb 2020, at 10:49 am, Alex Zavatone via Groups.Io <zav@...> wrote:

Sorry, A bit groggy here.  If my previous assumption that autorelease isn’t needed is incorrect, then it might be  that the instance will be retained until the reference to it is cleared or the enclosing object is deallocated.


Re: NSAlert boxes ...

Peter Hudson
 

Thanks Graham and Alex. 
I had reached the same sort of conclusions - but could not find any corroborative info anywhere ....
Peter 

On 16 Feb 2020, at 23:59, Graham Cox <graham@...> wrote:

Normal rules require that you either autorelease it or release it when you’re done (assuming manual MM of course).

If no autorelease or release was required, then that would be an exception to normal rules, and NSAlert is not documented as an exception to those rules. However, the alert can stay on screen for a long time, and the event loop is running, albeit modally. That means that autorelease pools are getting drained. So *something* must be keeping the alert alive until the user dismisses it.

—Graham



On 17 Feb 2020, at 10:49 am, Alex Zavatone via Groups.Io <zav@...> wrote:

Sorry, A bit groggy here.  If my previous assumption that autorelease isn’t needed is incorrect, then it might be  that the instance will be retained until the reference to it is cleared or the enclosing object is deallocated.


Re: NSAlert boxes ...

Graham Cox
 

Normal rules require that you either autorelease it or release it when you’re done (assuming manual MM of course).

If no autorelease or release was required, then that would be an exception to normal rules, and NSAlert is not documented as an exception to those rules. However, the alert can stay on screen for a long time, and the event loop is running, albeit modally. That means that autorelease pools are getting drained. So *something* must be keeping the alert alive until the user dismisses it.

—Graham



On 17 Feb 2020, at 10:49 am, Alex Zavatone via Groups.Io <zav@...> wrote:

Sorry, A bit groggy here.  If my previous assumption that autorelease isn’t needed is incorrect, then it might be  that the instance will be retained until the reference to it is cleared or the enclosing object is deallocated.


Re: NSAlert boxes ...

Alex Zavatone
 

On Feb 16, 2020, at 5:04 PM, Graham Cox <graham@...> wrote:

Hi Peter,

FWIW, I’ve always done exactly the same as this too, and have never had an issue.

My understanding (which may be wrong) is that the modal loop that runs the alert temporarily retains it, so you are safe no matter whether the alert is released by you afterwards, or autoreleased.

The point is, your code follows the normal rules. There’s no special case for NSAlert or other modal dialogs, because internal code behind the scenes makes sure the normal rules apply.

—Graham
Sorry, A bit groggy here. If my previous assumption that autorelease isn’t needed is incorrect, then it might be that the instance will be retained until the reference to it is cleared or the enclosing object is deallocated.

In any case, it’s an easy check.

Re: NSAlert boxes ...

Graham Cox
 

Hi Peter,

FWIW, I’ve always done exactly the same as this too, and have never had an issue.

My understanding (which may be wrong) is that the modal loop that runs the alert temporarily retains it, so you are safe no matter whether the alert is released by you afterwards, or autoreleased.

The point is, your code follows the normal rules. There’s no special case for NSAlert or other modal dialogs, because internal code behind the scenes makes sure the normal rules apply.

—Graham



On 17 Feb 2020, at 12:17 am, Peter Hudson via Groups.Io <Peter.hudson@...> wrote:

Hi There

I see from the docs that when you create an NSAlert that you should dispose of it yourself.
My code for creating a simple alert and using it looks like this :-


NSAlert *alert = [[[NSAlert alloc] init] autorelease];
alert.messageText = @:Some message or other”;
[alert addButtonWithTitle:@"Create category"];
[alert addButtonWithTitle:@"Cancel"];
       
NSModalResponse choice = [alert runModal];

Etc …..

Is the use of an autorelease here O.K. ?

It certainly seems to work …..



Peter