简体   繁体   中英

how to immediately wake up the daemon by sending him a SIGUSR1 signal

I wrote a program deamon which copy files with one folder to another .I have to implement SIGUSR1 which immediately wake up the daemon by sending him a SIGUSR1 signal. I do not know what I did wrong ,I use command kill -SIGUSR1 ,maybe wrong command?.Somebody know what is wrong with this code ?I did not have any warning after compiled this program,but just nothing happend

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <dirent.h>
#include <fcntl.h>
#include <signal.h>

#define _XOPEN_SOURCE ;

int recursion = 0; //1 if enabled, otherwise 0
int sleepTime = 300;
int fileLimit = 0;
int signaL = 0;
int exitSignal = 0;
int buffer = 1000;

//Returns 0 if arguments are correct otherwise returns 1
int readArguments(int number, char **argv, char *source, char *goal);
int checkFileType(struct stat file);
int copy(char *source, char *target, mode_t mask);
int copy_map(char *source, char *target, struct stat *Source);
void syncCopy(char *source, char *target);
void syncRemove(char *source, char *target);


void my_handler(int sig)
{
    syslog(LOG_INFO, "Daemon received signal SIGUSR1\n");
    signaL = 1;
}

void exitFunction(int sig)
{
    syslog(LOG_INFO, "Daemon received signal SIGUSR2\n");
    exitSignal = 1;
}
int main(int argc, char **argv)
{
    //char tables for paths
    char source[500], goal[500];
    struct stat Source, Goal;
    struct sigaction my_action, old_action;

    //checking and reading arguments
    if (readArguments(argc, argv, source, goal) == 1)
        exit(-1);

    //checking paths

    //checking  if argv[1] and argv[2] are existing paths
    if (lstat(source, &Source) != 0 || lstat(goal, &Goal) != 0) //bad result
    {
        printf("One of the paths or both dont exist\n");
        exit(-1);
    }

    if (checkFileType(Source) != 0)
    {
        printf("Source path is not path to folder");
        exit(-1);
    }

    if (checkFileType(Goal) != 0)
    {
        printf("Goal path is not path to folder");
        exit(-1);
    }

    //forking the parent process
    pid_t pid;
    // Fork off the parent process  and create new
    pid = fork();
    //if failure
    if (pid < 0)
    {
        exit(-1);
    }
    // if it is native process
    else if (pid > 0)
    {
        return 0;
    }
    //if pid==0 then it is childs process

    //now we have to umask in order to write to any files(for exmaple logs)

    umask(0);
    openlog("logFile", LOG_PID, LOG_DAEMON);
    syslog(LOG_INFO, "Deamon has just started running\n");

    pid_t sid = setsid();
    if (sid < 0)
    {
        syslog(LOG_ERR, "Error with session opening\n");
        exit(-1);
    }

    //SIGNAL SIGUSR1
    my_action.sa_handler = my_handler;
    sigfillset(&my_action.sa_mask);
    my_action.sa_flags = 0;
    if (sigaction(SIGUSR1, &my_action, &old_action) < 0)
    {
        syslog(LOG_ERR, "Error with the use of  SIGUSR1 signal\n");
        exit(-1);
    }

    //SIGNAL SIGUSR2 for exiting daemon
    my_action.sa_handler = exitFunction;
    sigfillset(&my_action.sa_mask);
    my_action.sa_flags = 0;
    if (sigaction(SIGUSR2, &my_action, &old_action) < 0)
    {
        syslog(LOG_ERR, "Error with the use of  SIGUSR2 signal\n");
        exit(-1);
    }

    while (!exitSignal)
    {
        sleep(sleepTime);
        switch (signaL)
        {
        case 0:
            syslog(LOG_INFO, "Demon started working after %ds\n", sleepTime);
            break;

        case 1:
        {
            syslog(LOG_INFO, "Demon started working after SIGUSR1 signal\n");
            signaL = 0; //Need to reeset signaL
            break;
        }
        }

        syncCopy(source, goal);
        syncRemove(source, goal);
        syslog(LOG_INFO, "Demon has just  gone to sleep");
    }

    //at the end of program we need to close log using
    syslog(LOG_INFO, "Demon has stopped\n");
    closelog();

    return 0;
}

Use command as kill -10 <pid> for SIGUSR1 and kill -12 <pid> for SIGUSR2 .

 kill -l // command to know the signal number.

Also make variable signaL , exitSignal as volatile sig_atomic_t type.

WHY volatile ?

when a global variable updated in signal handler is periodically checked in some other function for appropriate action, we should always declare them using the volatile attribute in order to prevent the compiler from performing optimizations that result in the variable being stored in a register. In worst case, updated value of variable(updated in handler context) won't be visible to function polling for the variable.

WHY sig_atomic_t ?

Reading and writing global variables may involve more than one machine- language instruction, and a signal handler may interrupt the main program in the middle of such an instruction sequence. (We say that access to the variable is nonatomic.) For this reason, the C language standards and SUSv3 specify an integer data type, sig_atomic_t , for which reads and writes are guaranteed to be atomic. Thus, a global flag variable that is shared between the main program and a signal handler should be declared as follows:

volatile sig_atomic_t signaL;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM