Archived

This forum has been archived. Please start a new discussion on GitHub.

signal handling and ice::Application

I am using Ice::Application on linux. My application needs to trap SIGINT to do some cleaning up on its own account. However, Ice::Application also hooks the signal to do its own cleanup.

Is there some way I can call Ice's cleanup from mine? Or my cleanup from Ice's?

Should I just install my own signal handler and make sure I do all the required Ice cleanup?

Suggestions welcome.

John

Comments

  • matthew
    matthew NL, Canada
    Why can't you cleanup after communicator->waitUntilShutdown(); returns?

    Regards, Matthew
  • Well, there's a bit more to it than I told you.

    My application code contains a select() call with infinite timeout. It receives data, and makes Ice calls in response.

    When someone types ctrl-C, I need the select to return. Currently it doesn't, because (I think) the Ice application class has masked it out. So I explicitly unmask SIGINT. However I don't know if there is some good reason why Ice masked it out.

    Actually I think that does what is needed, because I can then simply return from the run() function and the Application class will clean up everything for me.

    So I guess the remaining question is why does Ice (apparently) mask out SIGINT, and does it matter that I have re-enabled it?

    John
  • matthew
    matthew NL, Canada
    You probably should not interfere with the SIGINT handler that Ice installs. Note that if you want your app to be portable there is very little you can actually do in a signal handler anyway.

    A solution that comes to mind is that you could start a thread which does the select() and posts Ice requests. After waitForShutdown() returns then you could cause select() to terminate and shutdown your select()'ing thread.

    Regards, Matthew
  • bernard
    bernard Jupiter, FL
    The Application class is just a helper class. If it interferes with what you're trying to do, just don't use Application. You don't have to use Application (or the CtrlCHandler class) to use Ice, and without them, signal handling is entirely up to you.

    Cleaning up Ice is not difficult, you just need to destroy the communicator(s) that you create.

    Cheers,
    Bernard
  • bernard wrote:
    The Application class is just a helper class. If it interferes with what you're trying to do, just don't use Application. You don't have to use Application (or the CtrlCHandler class) to use Ice, and without them, signal handling is entirely up to you.

    Cleaning up Ice is not difficult, you just need to destroy the communicator(s) that you create.

    Well yes, but the Application helper class is, well, helpful. :)

    The CtrlCHandler is also useful / helpful to encapsulate platform-dependant signal handling differences between Win32 and Linux...

    I created a ChainedCtrlCHandler (which uses CtrlCHandler) and an Application2 (modified the existing Application). This lets me create an interrupt chain quite easily.

    It works in the testing I've done but I'm wondering, is there a reason that ya'll don't support something similar wrt CtrlCHandler (i.e. allowing users to add signal handler callbacks?)

    Regards,
    Brendan
  • bernard
    bernard Jupiter, FL
    The CtrlCHandler use callbacks: you register a callback function with your CtrlCHandler object and this callback gets called when one of the CTRL-C -like signals is sent to this process.

    There is one callback per CtrlCHandler object, and only one CtrlCHandler per process. We did not encounter any situation where this would not be flexible enough.

    Most of the time, you just want to shutdown or destroy your communicator in this callback, and that's exactly what Application does for you (with a CtrlCHandler object in its implementation). Why are you doing in your chained callbacks?

    Cheers,
    Bernard
  • bernard wrote:
    The CtrlCHandler use callbacks: you register a callback function with your CtrlCHandler object and this callback gets called when one of the CTRL-C -like signals is sent to this process.

    There is one callback per CtrlCHandler object, and only one CtrlCHandler per process. We did not encounter any situation where this would not be flexible enough.

    Most of the time, you just want to shutdown or destroy your communicator in this callback, and that's exactly what Application does for you (with a CtrlCHandler object in its implementation). Why are you doing in your chained callbacks?


    Hey Bernard!

    Thanks for the reply.

    First, in thinking through my reply to you I realized I had gone down the 'chained interrupt handler' route last week because I had initially thought that I'd like to get the interrupt before Application.

    I realized that what I'd like to do is simpler - use Application and still be able to supply my own CtrlCHandlerCallback for several scenarios which are related to how I like to cleanup resources on app termination.

    Scenarios:

    1) I have a server FooI which hands out bidirectional BarI objects. Before I terminate I'd like to send a message to all outstanding BarI objects that I'm terminating.

    2) My application has various objects and I'd like to gracefully dispose of them before destroying the communicator.

    To support this I created Application3 using Application which simply added a method 'static void userInterrupt(IceUtil::CtrlCHandlerCallback)'.

    I provide my own interrupt handler which signals my app to do a graceful shutdown and eventually destroy the communicator.

    As you've noted the Application class is a helper class and I don't need to use it. Still it seems to me desireable to allow the ability to specify an alternate CtrlCHandlerCallback and still use Application.

    Regards,
    Brendan
  • mes
    mes California
    Hi Brendan,

    I agree that what you've described would be generally useful, but I don't think that Application subclasses really need to use CtrlCHandler directly. Wouldn't it be sufficient if Application provided a method like this?
    virtual bool interrupt(int sig);
    
    The default implementation of interrupt would do nothing, but an interested subclass could override interrupt to perform special actions before the communicator is shutdown or destroyed. It wouldn't be called if interrupts were being ignored. The subclass could return true to indicate that shutdown should proceed, or false to abort shutdown.

    Would that work for your case?

    Take care,
    - Mark
  • Hey Mark!

    Off the top of my head I think that would be sufficient.

    In the 1) scenario I described previously I do end up destroying the communicator on the interrupt.

    Another way I could have handled it would be to set a flag when I catch the signal and then another 'housekeeping' thread could periodically check it and then initiate shutdown.

    So in this later scenario I wouldn't be destroying the communicator during the interrupt and so wouldn't want subsequent interrupt processing by Application to destroy the communicator either.

    Your comment that the "subclass could return true to indicate that shutdown should proceed, or false to abort shutdown." indicates that I could return false to prevent Application from destroying the communicator. My 'housekeeping' thread would then initiate shutdown and my app would terminate gracefully.

    If that's a correct assumption, then yes, I think this would be an elegant solution.

    Thanks!
    Brendan
  • mes
    mes California
    Hi,

    You could handle scenario 1 directly in interrupt() if you like, or interrupt() could launch a new thread and return false. However, it's not clear to me why you'd need a separate thread.

    Take care,
    - Mark
  • Hey Mark!

    Yup, Scenario 1 was implemented in my callback.

    Wrt Scenario 2 I'm thinking of another project I worked on. It used an event-driven architecture where only a single 'main' 'scheduler' thread was allowed to interact w/the library. Async events from other threads would be converted to events run on the main thread (including app termination).

    Regards,
    Brendan