0

I've created a program that creates a daemon, which in turn spawns and terminates a child process (a "mole") upon receiving a signal. When I send a signal to the process (kill -USR1 589), it kills the daemon too... It also seems to not execute the mole program (program that logs what mole popped up) that I've created. What am I doing incorrectly? Please help!!

#define MAXMOLES 2
//pid_t moles [MAXMOLES] = {-1,-1};
pid_t pid_child_mole;
int num;

void handler(int signum){
//signal handler that kills child and forks a new one OR kills child
    //and shuts down daemon
    if (signum == SIGTERM){
        kill (pid_child_mole,SIGTERM);
        exit(0);
    }
    if(signum == SIGUSR1){
        if(num == 0 && pid_child_mole > 0){
            kill(pid_child_mole,SIGCHLD);
        }
        num = rand() % 2;
        char *snum;
        sprintf(snum,"%d",num+1);
        char *mArgv[MAXMOLES] = {"mole",snum};
        pid_child_mole=fork();
            if(pid_child_mole==0){
                execv(mArgv[0],mArgv);
            }
        (void) signal(SIGUSR1, handler);
    }//if sigusr1
    if(signum == SIGUSR2){
        if(num == 1){
            kill(pid_child_mole,SIGCHLD);
        }
        num = rand() % 2;
        char *snum;
        sprintf(snum,"%d",num+1);
        char *mArgv[MAXMOLES] = {"mole",snum};
        pid_child_mole=fork();
            if(pid_child_mole==0){
                execv(mArgv[0],mArgv);
            }
        (void) signal(SIGUSR2, handler);
    }//if sigusr2
}
int main(int argc, char* argv[]){
    int fd0, fd1, fd2;
    pid_t process_id = 0;
    pid_t sid = 0;
// Create child process
    process_id = fork();
    if (process_id < 0) {// Indication of fork() failure
        printf("fork failed!\n");
        exit(1);// Return failure in exit status
    }
// PARENT PROCESS. Need to kill it.
    if (process_id > 0){
        printf("process_id of child process %d \n", process_id);
    // return success in exit status
        exit(0);
    }
//unmask the file mode
    umask(0);
    //set new session
    sid = setsid();
    if(sid < 0){
        // Return failure
        exit(1);
    }
// Change the current working directory to root.
    chdir("/");
// Close stdin. stdout and stderr
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
// Open a log file in write mode.
    //fp = fopen ("Log.txt", "w+");
    fd0 = open("/dev/null", O_RDWR);
    fd1 = dup(0);
    fd2 = dup(0);
    (void) signal(SIGTERM, handler);
    (void) signal(SIGUSR1, handler);
    (void) signal(SIGUSR2, handler);
    //num = rand() % 2;
    pid_child_mole=fork();
    while (1)
    {
        //Dont block context switches, let the process sleep for some time
        sleep(1);
    // Implement and call some function that does core work for this daemon.
        if(pid_child_mole == 0) {
            /* This is done by the child process. */
            num = rand() % 2;
            char *snum;
            sprintf(snum,"%d",num+1);
            char *mArgv[MAXMOLES] = {"mole",snum};
            execv(mArgv[0],mArgv );
            /* If execv returns, it must have failed. */
            printf("Unknown command\n");
            exit(0);
          }

    }
    //fclose(fp);
    close(fd0);
    close(fd1);
    close(fd2);
    return (0);
}

Mole program:

int main(int argc, char* argv[]){
    char *file_contents;
    FILE *fp;
    if( access( "Lab6_Daemon\\lab6.log", F_OK ) != -1 ) {
        // file exists
        fp= fopen ("Lab6_Daemon\\lab6.log", "r+");
    } else {
        // file doesn't exist
        fp= fopen ("Lab6_Daemon\\lab6.log", "a+");
    }
    fseek(fp, 0, SEEK_END);
    char *s;
    if(strcmp(argv[1],"1") == 0)
        s="Pop mole1";
    else
        s="Pop mole2";
    fprintf(fp, "%s\n",s);
    fclose(fp);
}

REVISED handler & function that handler calls:

void handler(int signum){
//signal handler that kills child and forks a new one OR kills child
    //and shuts down daemon
    if (signum == SIGTERM){
        kill (process_id,SIGTERM);
        exit(0);
    }
    if(signum == SIGUSR1)
        processSigNum(signum,0);
    else if (signum == SIGUSR2)
        processSigNum(signum,1);
    (void) signal(signum, handler);
}

void processSigNum (int sig, int moleNum){
    static int count =0;
    printf("\nThis is moleNum: %d with PID %d", moleNum+1,pid_child_mole[moleNum]);
    if(pid_child_mole[moleNum]>0){
        kill(pid_child_mole[moleNum],SIGKILL);
        pid_child_mole[moleNum] = 0;
    }
    int num = rand() % 2;//new moleNumber
    printf("\nNEW moleNum: %d", num+1);
    char snum[2];//used to store num as a char* and increment so that is it is
                //mole 1 or 2 instead of 0 or 1
    sprintf(snum,"%d",num+1);
    char *mArgv[] = {"mole",snum,0};
    if (pid_child_mole[num] >0)
        printf("\nMOLE %d ALREADY EXISTS!!",num);
    else{
        pid_child_mole[num]=fork();
        count++;
        if(pid_child_mole[num]==0)
            execv(mArgv[0],mArgv);

    }
    printf("\n\n");
}

Even when I kill the child process from the command line, the process # stays on but the command name changes from "mole 2" to "(mole)":

718 ?? 0:00.01 ./spiritd

719 ?? 0:00.00 (mole)

725 ?? 7:48.36 mole 2

loveusc1
  • 1
  • 1
  • Shouldn't the child's fopen be "w+"? If that doesn't work, try using the full path for the log files. Also, use fsopen for shared opening in case some other process already has the file open for writing or there are zombie children. – cup Nov 17 '14 at 05:46
  • Backslashes in the log file name of the mole program are strongly reminiscent of Windows — and are extremely rare on Linux. There's a TOCTOU (Time of Check, Time of Use) problem with the use of `access()` and then `fopen()`. You should simply use `fopen(filename, "a")` since that will create the file if it doesn't exist and won't truncate the file if it does exist, and all writes will always occur at the end (so the `fseek()` is irrelevant too). – Jonathan Leffler Nov 17 '14 at 06:37

1 Answers1

3

You've got a problem with your execv() code:

char *mArgv[MAXMOLES] = {"mole",snum};
execv(mArgv[0],mArgv );

The argument list needs to be terminated with a null pointer:

char *mArgv[] = { "mole", snum, 0 };
execv(mArgv[0], mArgv);

Also, in the handler code (and in the main program), you have:

char *snum;
sprintf(snum,"%d",num+1);

This is lethal; you need to allocate space for snum. In this case, the fix is simple:

char snum[16];
sprintf(snum, "%d", num+1);

You could use:

char snum[16];
snprintf(snum, sizeof(snum), "%d", num+1);

but it hardly seems necessary.

Another pair of related problems are:

  1. Because you cd to the root directory, the mole program won't be found to be executed unless you created it in the root directory — which would be an abominable thing to be doing.
  2. Because you cd to the root directory, (if it is run at all) the mole program will try to create its log file in the root directory — but it should not be able to write to files in the root directory.

You should not be running test code as user root or developing as root. It is too dangerous.

I observe that while it might be OK to put a polished, production-ready daemon into the background with no log file and standard output and standard error connected to /dev/null, it makes debugging extremely hard. Since few programs are ever bug free, you should basically always connect your daemons with standard output and standard error going to a log file (opened in append mode, so that if you truncate the log file, the writes will still occur at the end of the now truncated file). For daemons, you should probably record the time of each message, and quite probably the PID too. A standard logging package of functions can be used to automate this. Without the log files, you can't reliably report on problems, so you're running blind, and running blind causes you to trip over and get hurt.

I'm not sure these are the only problems, but they might well be sufficient to account for most of your problems.


Revised mole.c

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    FILE *fp = fopen("/tmp/mole.log", "a");
    if (fp != 0)
    {
        time_t now = time(0);
        struct tm *utc = gmtime(&now);
        char timestamp[32];
        strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%SZ", utc);
        char *s;
        if (argc > 1 && strcmp(argv[1], "1") == 0)
            s = "Pop mole1";
        else
            s = "Pop mole2";
        fprintf(fp, "%s - %5d: %s\n", timestamp, (int)getpid(), s);
        fclose(fp);
    }
    return 0;
}

The main differences between this program and its predecessor is that it uses a fixed log file name and records the time and PID in the log file.

Revised moletrap.c

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>   /* umask() */
#include <signal.h>
#include <unistd.h>
#include "stderr.h"

static pid_t pid_child_mole;
static int num;

// signal handler that kills child and forks a new one OR kills child
// and shuts down daemon
static void handler(int signum)
{
    if (signum == SIGTERM)
    {
        err_remark("Send SIGTERM to %d\n", (int)pid_child_mole);
        kill(pid_child_mole, SIGTERM);
        err_remark("Exiting\n");
        exit(0);
    }
    else if (signum == SIGUSR1)
    {
        if (num == 0 && pid_child_mole > 0)
        {
            err_remark("Send SIGCHLD to %d\n", (int)pid_child_mole);
            kill(pid_child_mole, SIGCHLD);
        }
        num = rand() % 2;
        char snum[16];
        sprintf(snum, "%d", num + 1);
        char *mArgv[] = { "mole", snum, 0 };
        pid_child_mole = fork();
        if (pid_child_mole == 0)
        {
            err_remark("about to execute %s %s\n", mArgv[0], mArgv[1]);
            execv(mArgv[0], mArgv);
            err_syserr("failed (1) to execute %s %s\n", mArgv[0], mArgv[1]);
        }
        (void) signal(SIGUSR1, handler);
    }
    else if (signum == SIGUSR2)
    {
        if (num == 1)
        {
            err_remark("Send SIGCHLD to %d\n", (int)pid_child_mole);
            kill(pid_child_mole, SIGCHLD);
        }
        num = rand() % 2;
        char snum[16];
        sprintf(snum, "%d", num + 1);
        char *mArgv[] = { "mole", snum, 0 };
        pid_child_mole = fork();
        if (pid_child_mole == 0)
        {
            err_remark("about to execute %s %s\n", mArgv[0], mArgv[1]);
            execv(mArgv[0], mArgv);
            err_syserr("failed (2) to execute %s %s\n", mArgv[0], mArgv[1]);
        }
        (void) signal(SIGUSR2, handler);
    }
    else
        err_remark("received unexpected signal %d\n", signum);
}

int main(int argc, char **argv)
{
    const char *logfile = "/tmp/moletrap.log";
    err_setarg0(argv[argc - argc]);
    err_setlogopts(err_getlogopts() | ERR_STAMP | ERR_PID);

    // Create child process
    pid_t process_id = fork();
    if (process_id < 0)  // Indication of fork() failure
        err_syserr("fork() failed\n");

    if (process_id > 0)
    {
        // PARENT PROCESS exits successfully
        printf("process ID of child process %d \n", process_id);
        exit(0);
    }

    // unmask the file mode
    umask(0);
    // set new session
    pid_t sid = setsid();
    if (sid < 0)
        err_syserr("setsid() failed\n");

    // Change the current working directory to root.
    // if (chdir("/") != 0)
    //     err_syserr("chdir() failed\n");

    // Redirect standard input from /dev/null
    close(STDIN_FILENO);
    if (open("/dev/null", O_RDONLY) < 0)
        err_syserr("failed to open /dev/null\n");

    // Redirect standard output and standard error to a log file
    int fd1 = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
    if (fd1 < 0)
        err_syserr("failed to open %s\n", logfile);
    if (dup2(fd1, STDOUT_FILENO) < 0)
        err_syserr("failed to send standard output to log file %s\n", logfile);
    if (dup2(fd1, STDERR_FILENO) < 0)
        err_syserr("failed to send standard error to log file %s\n", logfile);
    close(fd1);

    err_remark("Started\n");

    (void) signal(SIGTERM, handler);
    (void) signal(SIGUSR1, handler);
    (void) signal(SIGUSR2, handler);
    pid_child_mole = fork();
    while (1)
    {
        sleep(1);
        err_remark("Sleepers awake, salute ...\n");
        if (pid_child_mole == 0)
        {
            int num = rand() % 2;
            char snum[16];
            sprintf(snum, "%d", num + 1);
            char *mArgv[] = { "mole", snum, 0 };
            err_remark("about to execute %s %s\n", mArgv[0], mArgv[1]);
            execv(mArgv[0], mArgv );
            err_syserr("failed (3) to execute %s %s\n", mArgv[0], mArgv[1]);
        }
    }

    return(0);
}

This revision uses the original signal handling code, warts and all. In theory, it shouldn't do all the things it does in the signal handler, but it works 'OK'. OTOH, if anything went wrong, there'd be nothing to do except rewrite the code.

The code uses my "stderr.h" header and implicitly the implementation stderr.c. This radically simplifies the error reporting coding here: err_syserr() reports an error and the system error message based on errno and exits, while err_remark() writes a message and returns to the calling code. The err_setarg0() function records the program name (conventionally based on argv[0]); err_getlogopts() reports the current log option settings, and err_setlogopts() sets the same values plus ERR_PID (to record the PID on each line of output) and ERR_STAMP (to timestamp each line of output). The header is 150 lines (93 non-blank, non-comment lines); the source is 608 lines (424 non-blank, non-comment lines) — far too big to be shown here. See my profile if you want the code.

Sample command sequences

$ ./moletrap        # Reported 9424
$ kill -USR2 9424
$ kill -USR2 9424
$ kill -USR1 9424
$

$ ./moletrap        # Reported 9456
$ kill -USR2 9456
$ kill -USR2 9456
$ kill -USR1 9456
$ kill -USR1 9456
$ kill -TERM 9456
$ kill -TERM 9456
$

$ ./moletrap        # Reported 9499
$ kill -USR2 9499
$ kill -USR2 9499
$ kill -USR2 9499
$ kill -USR1 9499
$ kill -USR1 9499
$ kill -USR1 9499
$ kill -TERM 9499
$

Sample mole.log

2014-11-20 05:28:49Z -  9425: Pop mole2
2014-11-20 05:29:12Z -  9428: Pop mole2
2014-11-20 05:33:36Z -  9457: Pop mole2
2014-11-20 05:34:00Z -  9462: Pop mole2
2014-11-20 05:34:02Z -  9463: Pop mole1
2014-11-20 05:36:54Z -  9500: Pop mole2
2014-11-20 05:37:07Z -  9501: Pop mole2
2014-11-20 05:37:08Z -  9504: Pop mole2
2014-11-20 05:37:09Z -  9505: Pop mole2
2014-11-20 05:37:13Z -  9506: Pop mole1
2014-11-20 05:37:14Z -  9507: Pop mole1
2014-11-20 05:37:15Z -  9508: Pop mole1

Sample moletrap.log

moletrap: 2014-11-19 21:28:48 - pid=9424: Started
moletrap: 2014-11-19 21:28:49 - pid=9425: about to execute mole 2
moletrap: 2014-11-19 21:28:59 - pid=9426: about to execute mole 2
moletrap: 2014-11-19 21:28:59 - pid=9426: failed to execute mole 2
error (14) Bad address
moletrap: 2014-11-19 21:29:02 - pid=9424: Send SIGCHLD to 9426
moletrap: 2014-11-19 21:29:02 - pid=9427: about to execute mole 2
moletrap: 2014-11-19 21:29:02 - pid=9427: failed to execute mole 2
error (14) Bad address
moletrap: 2014-11-19 21:29:12 - pid=9428: about to execute mole 2

moletrap: 2014-11-19 21:33:35 - pid=9456: Started
moletrap: moletrap: 2014-11-19 21:33:36 - pid=9456: Sleepers awake, salute ...
2014-11-19 21:33:36 - pid=9457: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:36 - pid=9457: about to execute mole 2
moletrap: 2014-11-19 21:33:37 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:38 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:39 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:40 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:41 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:42 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:43 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:44 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:45 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:46 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:47 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:48 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:49 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:50 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:51 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:52 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:53 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:54 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:55 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:55 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:55 - pid=9460: about to execute mole 2
moletrap: 2014-11-19 21:33:55 - pid=9460: failed (2) to execute mole 2
error (14) Bad address
moletrap: 2014-11-19 21:33:56 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:57 - pid=9456: Send SIGCHLD to 9460
moletrap: 2014-11-19 21:33:57 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:57 - pid=9461: about to execute mole 2
moletrap: 2014-11-19 21:33:57 - pid=9461: failed (2) to execute mole 2
error (14) Bad address
moletrap: 2014-11-19 21:33:58 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:59 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:00 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:00 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:00 - pid=9462: about to execute mole 2
moletrap: 2014-11-19 21:34:01 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:02 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:02 - pid=9463: about to execute mole 1
moletrap: 2014-11-19 21:34:03 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:04 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:05 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:06 - pid=9456: Send SIGTERM to 9463
moletrap: 2014-11-19 21:34:06 - pid=9456: Exiting

moletrap: 2014-11-19 21:36:53 - pid=9499: Started
moletrap: moletrap: 2014-11-19 21:36:54 - pid=9499: Sleepers awake, salute ...
2014-11-19 21:36:54 - pid=9500: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:54 - pid=9500: about to execute mole 2
moletrap: 2014-11-19 21:36:55 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:56 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:57 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:58 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:59 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:00 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:01 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:02 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:03 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:04 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:05 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:06 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:07 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:07 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:07 - pid=9501: about to execute mole 2
moletrap: 2014-11-19 21:37:08 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:08 - pid=9499: Send SIGCHLD to 9501
moletrap: 2014-11-19 21:37:08 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:08 - pid=9504: about to execute mole 2
moletrap: 2014-11-19 21:37:09 - pid=9499: Send SIGCHLD to 9504
moletrap: 2014-11-19 21:37:09 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:09 - pid=9505: about to execute mole 2
moletrap: 2014-11-19 21:37:10 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:11 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:12 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:13 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:13 - pid=9506: about to execute mole 1
moletrap: 2014-11-19 21:37:14 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:14 - pid=9499: Send SIGCHLD to 9506
moletrap: 2014-11-19 21:37:14 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:14 - pid=9507: about to execute mole 1
moletrap: 2014-11-19 21:37:15 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:15 - pid=9499: Send SIGCHLD to 9507
moletrap: 2014-11-19 21:37:15 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:15 - pid=9508: about to execute mole 1
moletrap: 2014-11-19 21:37:16 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:17 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:18 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:19 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:20 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:21 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:21 - pid=9499: Send SIGTERM to 9508
moletrap: 2014-11-19 21:37:21 - pid=9499: Exiting

The '(24) Bad address' errors were because I'd only fixed two of the three places where execv() is used; fixing the third one eliminated the errors. You can see the development of the error handling; the first set didn't identify which 'failed to execute' message was giving the trouble; the second set showed that it was 'failed (2) to execute', which made it trivial to see the problem. Watch and learn!

Using "Sleepers awake, salute …" is a (bad) joke and a mixup; it just shows the iterations of the loop with time passing. (See Wachet auf at Wikipedia, and Christians Awake, Salute the Happy Morn.)

This shows your code at work. I'm not convinced the SIGCHLD signals are of any relevance whatsoever, but I left them in. The children die promptly anyway, and not because of being sent SIGCHLD. I've not checked for zombies — beware the sleeping dead.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I'm really a novice at unix programming (as you can probably tell). I changed the directory and added null character so that it could find the mole program and that seems to work. But I still have a couple problems: 1)I can't seem to find the log file that the mole program should be creating. 2)I still can't kill the child process I also agree that it is a nightmare debugging this program-- but I am not sure how to create a log that recods the time of each message and PID. – loveusc1 Nov 17 '14 at 17:59
  • The parent process could be made responsible for giving the mole standard output and standard error connected to the appropriate log file. You could, for example, create a directory `/tmp/mole-logs` and place log files in there, perhaps with the date/time and/or PID in the log file name. Then the mole program would simply need to write the appropriate message to its standard output, and the info would be in the file whose location you know. Or you can write the mole program to open a file and write to it in the known location. Both work. – Jonathan Leffler Nov 17 '14 at 18:06
  • I suggest looking at the amount of work in your signal handler carefully. Standard C pretty much allows you to call `signal()` to reset the signal handler, `_exit()` or `_Exit()` to terminate, and to modify `volatile sigatomic_t` variables. POSIX is a lot more forgiving, but you should look at [How to avoid using `printf()` in a signal handler](http://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler/) to see more about what is and is not allowed (hint: `printf()` and `sprintf()` are not allowed, even in POSIX; strictly, even `strlen()` isn't allowed!). – Jonathan Leffler Nov 17 '14 at 18:10
  • And finally, I suggest you update your question adding your revised code (not overwriting the original, please). I'll look at it when I can, but there's this inconvenient thing called 'work' that has to be given some attention now and then. – Jonathan Leffler Nov 17 '14 at 18:11
  • I added the revised code with my comments about printfs. Can a handler call a function that uses printfs? I believe this program works except that it is not killing the moles...which of course is a big problem. – loveusc1 Nov 19 '14 at 18:30
  • @loveusc1: I've noted the update; I'll look later this evening. No, a signal handler function may not call other functions that invoke the verboten functions. Or, more accurately, it _can_ call them but the behaviour is undefined, and undefined behaviour in a signal handler is something to avoid at all costs, even more so than usual, because it can be really hard (much harder than usual) to recreate the aberrant behaviour that may occur (because it is typically extremely time sensitive). – Jonathan Leffler Nov 19 '14 at 22:14
  • @J.Leffler: Thanks so much for your help! I figured out that I just had to do a wait on my moles to stop it from making zombie processes...but if you can help me figure out how to convert an integer to a string without using sprintf when I call my mole program, that would be great :) – loveusc1 Nov 20 '14 at 00:00