0

I'm writing a console application Windows that creates some objects in the main thread and kicks those off into a loop, only exiting when the user uses the Ctrl-C interrupt.

Now, I've read a bit about how to write a proper interrupt handler in articles like this: http://msdn.microsoft.com/en-us/library/ms685049%28VS.85%29.aspx but I'm still confused about one thing. It seems like the interrupt handler leaves limited scope for local object cleanup. For instance, if I had a handler like so:

BOOL CtrlHandler ( DWORD fdwCtrlType )
  ... handle Ctrl-C 

and my main looked something like this:

int main() {
      DBClient db;
      DataPuller p;

      while (true) {
           ... do stuff until Ctrl-C comes in
      }

Even if I catch the Ctrl-C, there seems to be no way to do a proper cleanup of variables db and p without declaring them global, which I typically stay away from.

Is there a better way to do this, or am I missing something obvious? Thanks.

hda 2017
  • 59
  • 6
  • Why do you need to clean anything up - those are automatic variables, they should clean themselves up when you exit the function scope. – Kerrek SB Sep 19 '11 at 17:53
  • 1
    @Kerrek: A Ctrl-C sends the SIGINT signal to the processes. If not handled this causes the application to abort (without returning from the signal handler). Thus automatic variables are not cleaned up. – Martin York Sep 19 '11 at 17:57
  • @Tux: I thought the OP had installed a signal handler that would just set an appropriate exit conditional. – Kerrek SB Sep 19 '11 at 17:58

2 Answers2

2

You make your loop on a condition variable.

When you receive ctrl-C (SIGINT) you set the condition variable to false and return. The loop will then exit normally.

bool finished = false;

int main()
{
      DBClient db;
      DataPuller p;

      while (!finished)
      {
           // ... do stuff until Ctrl-C comes in
      }
}

// Signal handler or Control handler on windows
// Set finished = true.
Martin York
  • 257,169
  • 86
  • 333
  • 562
1

I don't think this can be done without at least one global. However, I think you only need one:

BOOL is_shutting_down = false;

BOOL CtrlHandler ( DWORD fdwCtrlType ) {
    switch( fdwCtrlType ) 
    { 
        // Handle the CTRL-C signal. 
        case CTRL_C_EVENT: 
            is_shutting_down = true;
            return( TRUE );
    }
}

int main() {
      DBClient db;
      DataPuller p;

      while (is_shutting_down == false) {
           ... do stuff until Ctrl-C comes in
      }

      //objects clean themselves automatically.
}

A side affect of a global "is_shutting_down" is that if it is set to true, destructors do not need to deallocate memory, since the OS will automatically reclaim it all anyway, which allows you to shut down FAST if you have a large number of small allocations.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158