0

Im writing a daemon in C that posts data to PostgreSQL database using libpq library. It has structure like this:

init(...) // init function, opens connection
while(1){export(...)} // sends commands

When someone kills the application, it leaves open connection on PostgreSQL server. I want to avoid that. Opening and closing connection in export(...) function is not an option, because this code is part of performance dependent framework.

Tomáš Šíma
  • 834
  • 7
  • 26

2 Answers2

1

You may install a signal handler to catch the application kill, and close the active connections from that handler:

#include "signal.h"
#include "stdio.h"
#include "stdlib.h"

void catch_sigint( int sig )
{
    /* Close connections */

    /*
     * The software won't exit as you caught SIGINT
     * so explicitly close the process when you're done
     */
    exit( EXIT_SUCCESS );
}

int main( void )
{
    /* Catches SIGINT (ctrl-c, for instance) */
    if( signal( SIGINT, catch_sigint ) == SIG_ERR )
    {
        /* Failed to install the signal handler */
        return EXIT_FAILURE;
    }

    /* Perform your operations */
    while( 1 );

    return EXIT_SUCCESS;
}
Macmade
  • 52,708
  • 13
  • 106
  • 123
  • The use of `signal()` is not recommended as not portable. Its use should be avoided. `sigaction()`, if available, is the preferred solution. – alk Jan 09 '13 at 17:01
  • Wrong! `signal` is ISO-C and `sigaction` is POSIX. So `signal` is in fact more portable. But I agree it's the old way, which have less options than `sigaction`. But also note than on most actual POSIX systems, `signal` is in fact implemented using `sigaction`. I used `signal` in my answer as the OP did not mention its platform, so the example will run even on non POSIX systems. – Macmade Jan 09 '13 at 17:06
  • I shouldn't have written "*... portable ...*" when mentioning a POSIX function as alternative, you are right (although I added the "*... if available ...*" disclaimer, btw). Anyway, even being ISO-C, this does not make sure each of `signal()`'s implementations behave similar. – alk Jan 09 '13 at 17:14
1

You have to implement a handler for signals that could terminate your program.

void handler_function(int signal) {
  //close db connection
  exit(signal);
}

  // somewhere in init:
{
  sigset_t sigs;
  struct sigaction siga_term;

  sigfillset( &sigs );

  siga_term.sa_handler = handler_funciton();
  siga_term.sa_mask = sigs;
  siga_term.sa_flags = 0;

  sigaction( SIGTERM, &siga_term, NULL );
}

consult how to intercept linux signals ? (in C)

Community
  • 1
  • 1
Dariusz
  • 21,561
  • 9
  • 74
  • 114