Hello everyone.
I have written the following program. It is a little daemon that checks
whether my IP Adress has changed every 30 seconds. Now I wanted the daemon
to catch SIGTERM and cleanup properly the strings myip and ip_buffer.
Since free should not be called within the Signal handler I used a Flag
variable that terminates the loop and after the loop free is called for both
variables.
Here is the code. Don't tell me syslog shouldn't be called within the signal
handler. It is just there to see what the program is doing and will be
removed once it is working.
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <syslog.h>
#include <signal.h>
#include "get_address.h"
#define RUN_MAIN_LOOP 0
#define EXIT_NOW 2
/* use an atomic Integer as flag variable */
volatile sig_atomic_t signal_flag;
void signal_handler(int sig)
{
switch(sig) {
case SIGHUP:
syslog(LOG_INFO, "SIGHUP received\n" );
break;
case SIGTERM:
signal (SIGTERM, SIG_IGN);
syslog(LOG_INFO, "Termination Signal received exiting...\n"
);
signal_flag = EXIT_NOW;
break;
}
}
int main (void) {
char * myip = malloc(16 * sizeof(char));
char * ip_buffer = malloc(16 * sizeof(char));
strncpy(myip, "000.000.000.000\0", 16);
strncpy(ip_buffer, "111.111.111.111\0", 16);
pid_t pid, sid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* Change the file mode mask */
umask(0);
/* Open any logs here */
openlog ("zone_update", LOG_PID, LOG_DAEMON);
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
exit(EXIT_FAILURE);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
exit(EXIT_FAILURE);
}
/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* Initialize the signal handler */
signal_flag = RUN_MAIN_LOOP;
signal(SIGCHLD,SIG_IGN); /* ignore child */
signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGHUP,signal_handler); /* catch hangup signal */
signal(SIGTERM,signal_handler); /* catch kill signal */
/* Main Loop */
while ( signal_flag != EXIT_NOW ) {
if ( get_address(&myip) != 0)
{
exit(EXIT_FAILURE);
}
if ( strncmp(ip_buffer, myip, 16 ) != 0 )
{
strncpy (ip_buffer, myip, 16);
syslog(LOG_INFO, "Current IP = %s \n", myip);
}
else
{
syslog(LOG_INFO, "Current IP is still %s and has not
changed\n", myip );
}
/* Wait for a given time */
sleep(30);
}
/* We are terminating now. Clean up */
syslog(LOG_INFO, "Got Sigterm.... Terminating.... \n" );
free(ip_buffer);
syslog(LOG_INFO, "Freed ip_buffer\n");
/* The code executes up to here */
free(myip);
syslog(LOG_INFO, "Tried to free myip\n");
closelog;
return 0;
}
Now if I run the program free(myip) get's called and an error appears in the
log files.
Sep 10 14:06:22 gecko zone_update[21246]: Current IP is still 178.94.229.210
and has not changed
Sep 10 14:06:37 gecko zone_update[21246]: Termination Signal received
exiting...
Sep 10 14:06:37 gecko zone_update[21246]: Got Sigterm.... Terminating....
Sep 10 14:06:37 gecko zone_update[21246]: Freed ip_buffer
Sep 10 14:06:37 gecko zone_update[21246]: *** glibc detected ***
./change_zone: free(): invalid pointer: 0x00007f54b4ad56c8 ***
My question is now why the second call to free doesn't work.
And how can write the code to properly clean up the variables.
Thanks for any reply Willem
--
View this message in context:
http://www.nabble.com/Linux-signal-Programming-freeing-memory-on-cleanup-tp25391730p25391730.html
Sent from the C-prog mailing list archive at Nabble.com.