Lynton Grice
Lynton Grice

Reputation: 1445

Correct way to shutdown C application to ensure CRITICAL sections completed?

I have a shutdown hook handler defined in a SINGLE threaded C application.

int main(int argc, char * argv[]){
    //Shutdown hook for CTRL-C
    (void) signal(SIGINT, shutdownHook);
    ...
    ...
}

So when the user hits CTRL-C the shutdown hook is initiated...

void shutdownHook(int sig){
    rc = wmq_sender_stop(errorStr);
    if (rc != 0){
        printf("\n%s\n", errorStr);
    }
    while(transactionRunning == TRUE){
        sleep(1);
        printf("Transaction still running\n");
    }
    ....
    ....
}

You can see above that I call a "wmq_sender_stop" routine (in a shared lib) that essentially sets a variable to FALSE to end a loop in that shared lib.

int wmq_sender_stop(char errorStr[ERROR_STR_LEN]){
       running = FALSE;
       ...
}

And that variable "running" will stop (hopefully) the main loop running in that shared lib.

while(running == TRUE){
...
...
}

The problem I am having is on my Linux box all works 100%...but when I install the application on a BIG powerful server it calls the "wmq_sender_stop" and sets the variable fine, but it seems like the application is running too fast on the server to allow the "while(running == TRUE)" variable to exit.....OR it is simply returning to the main application too fast and the "while(transactionRunning == TRUE)" loop just continuously runs...

Essentially on the BIG server if I hit CRTL-C the following is continuosly output to the screen:

Transaction still running
Transaction still running
Transaction still running
Transaction still running
Transaction still running
Transaction still running
...

Perhaps I need to make threads here and have intercommunication between them but is their no easier way to elegantly allow a "loop in a shared lib" to end it's "critical code / transactions" before shutting down even on extremely fast servers? And why does it work on my linux laptop?

And if I need to use threads what is the best and FASTEST way for them to comminucate? Currently I am using CALLBACKS....but am not sure what the best IPC is for threads?

Thanks for the help, much appreciated

Lynton

Upvotes: 0

Views: 390

Answers (2)

Dietrich Epp
Dietrich Epp

Reputation: 213558

Make sure that running (and transactionRunning, too) is declared as volatile. Otherwise, the C compiler may cache its value under some circumstances. For now, think of volatile as meaning "this value could get changed by a signal handler".

Note that you have to be careful with code like this:

rc = wmq_sender_stop(errorStr);

If you do that in a signal handler, you had better hope that that function is safe to call from a signal handler. Most functions aren't. (Even functions that are safe to call from multiple threads are unsafe to call from a signal handler.)

The last issue is that if your code is single-threaded, but you never return from your signal handler, how is your main loop supposed to exit? The signal handler runs in one of your application's existing threads. Generally the only thing you want to do in a signal handler is change the value of a global variable that is marked volatile and then return.

Upvotes: 2

alk
alk

Reputation: 70971

Why not just call wmq_sender_stop() and than leave the signal handler via return. The loop in the shared lib will exit and so your app will do, won't it?

Upvotes: 0

Related Questions