Using NSTerminateLater with a Status Item

  • Hi all,

    I'm facing a problem returning NSTerminateLater from applicationShouldTerminate: in a status item application...
    I've tried many things and followed the doc I've found, but nothing works as I'm expecting it to.

    In short, I want to delay the termination of my status item application (which has LSUIElement set to YES if that matters) so that I can clean some things up before exiting.

    It does work when I quit the application manually from the menu, but not at all when I'm restarting the computer. I've seen Terminal and other apps block the restart process to ask the user to confirm termination, so I guess what I want is feasible. I'm just probably missing some details...

    Here's what I do :

    in applicationShouldTerminate: I display a dialog using NSRunPanel. Depending on user choice, I either return NSTerminateNow or NSTerminateLater.
    When I return NSTerminateLater I initiate my clean up process, which makes some asynchronous calls to a device driver. When I receive the driver's response, I call [NSApp replyToApplicationShouldTerminate:YES].
    The entire process works perfectly fine when the app is being exited from the status item menu. If I do " > Restart" though, the AlertPanel shows (sometimes it doesn't even have the time to show up) but the system continues exiting and I don't have time to click anything.

    I've tried always returning NSTerminateLater, and then display the Alter Panel, but it doesn't change anything.

    So what am I doing wrong? Is there a requirement I don't meet? Does it have to be a document-based application?

    Also, would you have any clever way to debug that kind of situation? Tried remote debugging but the connection would just be shut on restart...

    Thanks a lot,
    Olivier Lance.
  • Hi Olivier.

    rdar://problem/6001460

    See http://lapcatsoftware.com/rdar/6001460/index.html for an explanation.

    In short, you won't be able to do it with a LSUIElement app.

    -Jeff

    On Feb 14, 2011, at 10:52 AM, Olivier Lance wrote:

    > Hi all,
    >
    > I'm facing a problem returning NSTerminateLater from applicationShouldTerminate: in a status item application...
    > I've tried many things and followed the doc I've found, but nothing works as I'm expecting it to.
    >
    > In short, I want to delay the termination of my status item application (which has LSUIElement set to YES if that matters) so that I can clean some things up before exiting.
    >
    > It does work when I quit the application manually from the menu, but not at all when I'm restarting the computer. I've seen Terminal and other apps block the restart process to ask the user to confirm termination, so I guess what I want is feasible. I'm just probably missing some details...
    >
    > Here's what I do :
    >
    > in applicationShouldTerminate: I display a dialog using NSRunPanel. Depending on user choice, I either return NSTerminateNow or NSTerminateLater.
    > When I return NSTerminateLater I initiate my clean up process, which makes some asynchronous calls to a device driver. When I receive the driver's response, I call [NSApp replyToApplicationShouldTerminate:YES].
    > The entire process works perfectly fine when the app is being exited from the status item menu. If I do " > Restart" though, the AlertPanel shows (sometimes it doesn't even have the time to show up) but the system continues exiting and I don't have time to click anything.
    >
    > I've tried always returning NSTerminateLater, and then display the Alter Panel, but it doesn't change anything.
    >
    > So what am I doing wrong? Is there a requirement I don't meet? Does it have to be a document-based application?
    >
    > Also, would you have any clever way to debug that kind of situation? Tried remote debugging but the connection would just be shut on restart...
    >
    > Thanks a lot,
    > Olivier Lance._______________________________________________
  • Hi Jeff,

    Well that's what I was afraid to learn...
    Gotta find a workaround then!

    Do you know if by any chance, something similar can be done from a process running as a service using launchd?

    Thanks a lot for you quick reply :)
    Olivier

    Le 14 févr. 2011 à 19:06, "Jeff Johnson" <publicposting...> a écrit :

    > Hi Olivier.
    >
    > rdar://problem/6001460
    >
    > See http://lapcatsoftware.com/rdar/6001460/index.html for an explanation.
    >
    > In short, you won't be able to do it with a LSUIElement app.
    >
    > -Jeff
    >
    >
    > On Feb 14, 2011, at 10:52 AM, Olivier Lance wrote:
    >
    >> Hi all,
    >>
    >> I'm facing a problem returning NSTerminateLater from applicationShouldTerminate: in a status item application...
    >> I've tried many things and followed the doc I've found, but nothing works as I'm expecting it to.
    >>
    >> In short, I want to delay the termination of my status item application (which has LSUIElement set to YES if that matters) so that I can clean some things up before exiting.
    >>
    >> It does work when I quit the application manually from the menu, but not at all when I'm restarting the computer. I've seen Terminal and other apps block the restart process to ask the user to confirm termination, so I guess what I want is feasible. I'm just probably missing some details...
    >>
    >> Here's what I do :
    >>
    >> in applicationShouldTerminate: I display a dialog using NSRunPanel. Depending on user choice, I either return NSTerminateNow or NSTerminateLater.
    >> When I return NSTerminateLater I initiate my clean up process, which makes some asynchronous calls to a device driver. When I receive the driver's response, I call [NSApp replyToApplicationShouldTerminate:YES].
    >> The entire process works perfectly fine when the app is being exited from the status item menu. If I do " > Restart" though, the AlertPanel shows (sometimes it doesn't even have the time to show up) but the system continues exiting and I don't have time to click anything.
    >>
    >> I've tried always returning NSTerminateLater, and then display the Alter Panel, but it doesn't change anything.
    >>
    >> So what am I doing wrong? Is there a requirement I don't meet? Does it have to be a document-based application?
    >>
    >> Also, would you have any clever way to debug that kind of situation? Tried remote debugging but the connection would just be shut on restart...
    >>
    >> Thanks a lot,
    >> Olivier Lance._______________________________________________
    >
  • On 14 Feb 2011, at 19:29, Olivier Lance wrote:

    > Hi Jeff,
    >
    > Well that's what I was afraid to learn...
    > Gotta find a workaround then!
    >
    I don't know if this would fly or not but...

    Rather than conventionally returning NSTerminateLater you could try, assuming your async driver calls are run loop sources, run the run loop as required within - applicationShouldTerminate.

    This should allow you the opportunity to get a window on screen (though not necessarily using NSRunAlertPanel), process the user response, await the async callbacks and exit when your cleanup is done.

    Regards

    Jonathan Mitchell

    Developer
    Mugginsoft LLP
    http://www.mugginsoft.com

    > Do you know if by any chance, something similar can be done from a process running as a service using launchd?
    >
    > Thanks a lot for you quick reply :)
    > Olivier
    >
    > Le 14 févr. 2011 à 19:06, "Jeff Johnson" <publicposting...> a écrit :
    >
    >> Hi Olivier.
    >>
    >> rdar://problem/6001460
    >>
    >> See http://lapcatsoftware.com/rdar/6001460/index.html for an explanation.
    >>
    >> In short, you won't be able to do it with a LSUIElement app.
    >>
    >> -Jeff
    >>
    >>
    >> On Feb 14, 2011, at 10:52 AM, Olivier Lance wrote:
    >>
    >>> Hi all,
    >>>
    >>> I'm facing a problem returning NSTerminateLater from applicationShouldTerminate: in a status item application...
    >>> I've tried many things and followed the doc I've found, but nothing works as I'm expecting it to.
    >>>
    >>> In short, I want to delay the termination of my status item application (which has LSUIElement set to YES if that matters) so that I can clean some things up before exiting.
    >>>
    >>> It does work when I quit the application manually from the menu, but not at all when I'm restarting the computer. I've seen Terminal and other apps block the restart process to ask the user to confirm termination, so I guess what I want is feasible. I'm just probably missing some details...
    >>>
    >>> Here's what I do :
    >>>
    >>> in applicationShouldTerminate: I display a dialog using NSRunPanel. Depending on user choice, I either return NSTerminateNow or NSTerminateLater.
    >>> When I return NSTerminateLater I initiate my clean up process, which makes some asynchronous calls to a device driver. When I receive the driver's response, I call [NSApp replyToApplicationShouldTerminate:YES].
    >>> The entire process works perfectly fine when the app is being exited from the status item menu. If I do " > Restart" though, the AlertPanel shows (sometimes it doesn't even have the time to show up) but the system continues exiting and I don't have time to click anything.
    >>>
    >>> I've tried always returning NSTerminateLater, and then display the Alter Panel, but it doesn't change anything.
    >>>
    >>> So what am I doing wrong? Is there a requirement I don't meet? Does it have to be a document-based application?
    >>>
    >>> Also, would you have any clever way to debug that kind of situation? Tried remote debugging but the connection would just be shut on restart...
    >>>
    >>> Thanks a lot,
    >>> Olivier Lance.
  • On Feb 14, 2011, at 3:25 PM, <jonathan...> wrote:

    > On 14 Feb 2011, at 19:29, Olivier Lance wrote:
    >
    >> Hi Jeff,
    >>
    >> Well that's what I was afraid to learn...
    >> Gotta find a workaround then!
    >>
    > I don't know if this would fly or not but...
    >
    > Rather than conventionally returning NSTerminateLater you could try, assuming your async driver calls are run loop sources, run the run loop as required within - applicationShouldTerminate.
    >
    > This should allow you the opportunity to get a window on screen (though not necessarily using NSRunAlertPanel), process the user response, await the async callbacks and exit when your cleanup is done.

    No, if your app does not return from applicationShouldTerminate: within a certain number of seconds, your process will simply be killed.

    -Jeff
  • On 15 févr. 2011, at 16:55, Jeff Johnson wrote:
    > On Feb 14, 2011, at 3:25 PM, <jonathan...> wrote:
    >> I don't know if this would fly or not but...
    >>
    >> Rather than conventionally returning NSTerminateLater you could try, assuming your async driver calls are run loop sources, run the run loop as required within - applicationShouldTerminate.
    >>
    >> This should allow you the opportunity to get a window on screen (though not necessarily using NSRunAlertPanel), process the user response, await the async callbacks and exit when your cleanup is done.
    >
    > No, if your app does not return from applicationShouldTerminate: within a certain number of seconds, your process will simply be killed.

    I'm not even sure we can talk "seconds" here... I've tried doing a sleep in the applicationShouldTerminate:. When restarting, the application doesn't even wait a second....

    I was hoping something like this would work:

    • In applicationShouldTerminate: or applicationWillTerminate, spawn a process that would not be a NSBackgroundOnly/LSUIElement application.
    • Have a applicationShouldTerminate: implementation that returns NSTerminateLater and displays a modal message.

    In my idea, if the process ever had the time to launch and initialize, that would give me the delay I'm looking for... Unfortunately, though the process has enough time to launch (I can see its window appearing), it seems to be killed upon restart, and the dialog never appears :(

    If anybody can see a reason for that, or have another idea, I'll be more than glad to try it out!

    Thanks,
    Olivier
previous month february 2011 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28            
Go to today