tags:

views:

102

answers:

4

This is a pretty basic scenario but I'm not finding too many helpful resources. I have a C++ program running in Linux that does file processing. Reads lines, does various transformations, writes data into a database. There's certain variables (stored in the database) that affect the processing which I'm currently reading at every iteration because I want processing to be as up to date as possible, but a slight lag is OK. But those variables change pretty rarely, and the reads are expensive over time (10 million plus rows a day). I could space out the reads to every n iterations or simply restart the program when a variable changes, but those seem hackish.

What I would like to do instead is have the program trigger a reread of the variables when it receives a SIGHUP. Everything I'm reading about signal handling is talking about the C signal library which I'm not sure how to tie in to my program's classes. The Boost signal libraries seem to be more about inter-object communication rather than handling OS signals.

Can anybody help? It seems like this should be incredibly simple, but I'm pretty rusty with C++.

+1  A: 

There are several possibilities; it would not necessarily be overkill to implement all of them:

  • Respond to a specific signal, just like C does. C++ works the same way. See the documentation for signal().
  • Trigger on the modification timestamp of some file changing, like the database if it is stored in a flat file.
  • Trigger once per hour, or once per day (whatever makes sense).
wallyk
+1  A: 

I'd recommend checking out this link which gives the details on registering a signal.

Unless I'm mistaken, one important thing to remember is that any function inside an object expects a referent parameter, which means non-static member functions can't be signal handlers. I believe you'll need to register it either to a static member function, or some kind of global function. From there, if you have a specific object function you want to take care of your update, you'll need a way to reference that object.

Bryan
+6  A: 

I would handle it just like you might handle it in C. I think it's perfectly fine to have a stand-alone signal handler function, since you'll just be posting to a semaphore or setting a variable or some such, which another thread or object can inspect to determine if it needs to re-read the settings.

#include <signal.h>
#include <stdio.h>

/* or you might use a semaphore to notify a waiting thread */
static volatile sig_atomic_t sig_caught = 0;

void handle_sighup(int signum) 
{
    /* in case we registered this handler for multiple signals */ 
    if (signum == SIGHUP) {
        sig_caught = 1;
    }
}

int main(int argc, char* argv[]) 
{
    /* you may also prefer sigaction() instead of signal() */
    signal(SIGHUP, handle_sighup);

    while(1) {
        if (sig_caught) {
            sig_caught = 0;
            printf("caught a SIGHUP.  I should re-read settings.\n");
        }
    }

    return 0;
}

You can test sending a SIGHUP by using kill -1 `pidof yourapp`.

John Ledbetter
Oh duh. I was completely overthinking it and forgot that signal variables are what I want rather than direct invocation. *headdesk*
KernelM
If you want to be standards compliant, make sure to qualify your signal handler as `extern "C"`
R Samuel Klatchko
@R Samuel: That's a great point. I didn't even think about `extern "C"` since I was writing C code, but the OP will need it!
John Ledbetter
A: 

You can define a Boost signal corresponding to the OS signal and tie the Boost signal to your slot to invoke the respective handler.

anand.arumug