Kill the process before really call the kill function (signal problem) in C

Issue

struct job_t {              /* The job struct */
    pid_t pid;              /* job PID */
    int jid;                /* job ID [1, 2, ...] */
    int state;              /* UNDEF, BG, FG, or ST */
    char cmdline[MAXLINE];  /* command line */
};
struct job_t jobs[MAXJOBS]; /* The job list */

/* clearjob - Clear the entries in a job struct */
void clearjob(struct job_t *job) {
    job->pid = 0;
    job->jid = 0;
    job->state = UNDEF;
    job->cmdline[0] = '\0';
}

/* initjobs - Initialize the job list */
void initjobs(struct job_t *jobs) {
    int i;

    for (i = 0; i < MAXJOBS; i++)
    clearjob(&jobs[i]);
}

/* deletejob - Delete a job whose PID=pid from the job list */
int deletejob(struct job_t *jobs, pid_t pid) 
{
    int i;

    if (pid < 1)
    return 0;

    for (i = 0; i < MAXJOBS; i++) {
    if (jobs[i].pid == pid) {
        clearjob(&jobs[i]);
        nextjid = maxjid(jobs)+1;
        return 1;
    }
    }
    return 0;
}

/* fgpid - Return PID of current foreground job, 0 if no such job */
pid_t fgpid(struct job_t *jobs) {
    int i;

    for (i = 0; i < MAXJOBS; i++)
    if (jobs[i].state == FG)
        return jobs[i].pid;
    return 0;
}


/*********************functions above for prepare***********************/


/* 
 * waitfg - Block until process pid is no longer the foreground process
 */
void waitfg(pid_t pid)
{   
    sigset_t mask, prev, emp;
    sigfillset(&mask);

    sigprocmask(SIG_BLOCK, &mask, &prev);
    
    while (fgpid(jobs) == pid) {
        printf("waitfg\n");
        sigsuspend(&prev);  /* Just wait for a signal */
    }
        
    sigprocmask(SIG_SETMASK, &prev, NULL);
    return;
}


/* 
 * sigint_handler - The kernel sends a SIGINT to the shell whenver the
 *    user types ctrl-c at the keyboard.  Catch it and send it along
 *    to the foreground job.  
 */
void sigint_handler(int sig) 
{   
    int olderrno = errno;
    pid_t pid;

    pid = fgpid(jobs);
    if (pid == 0)
        return; /* Seem always return here */

    /* Just print something */
    Sio_puts("sigint runned: ");    /* But never print ? */
    Sio_putl((long) pid);
    Sio_puts("\n");

    kill(pid, SIGINT);


    errno = olderrno;    
    return;
}

/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.  
 */
void sigchld_handler(int sig) 
{
    int olderrno = errno;
    sigset_t mask_all, prev_all;
    pid_t pid;

    sigfillset(&mask_all);
    while ((pid = waitpid(-1, NULL, 0)) > 0) {  /* Reap child */
        sigprocmask(SIG_BLOCK, &mask_all, &prev_all);
        if (!deletejob(jobs, pid))
            Sio_puts("warning!: deletejob return 0\n");
        sigprocmask(SIG_SETMASK, &prev_all, NULL);
    }
    if (errno != ECHILD)
        Sio_error("waitpid error");
    errno = olderrno;
    return;
}


In my assumption this sequencing should be run in order of commands. But in fact it seems to run kill(pid, SIGINT);first, when the control reaches if (pid == 0), pid’s value is 0 which is another value When entering this function(i’m not sure).As the result, "sigint runned: " never print.

Another question:

void sigint_handler(int sig) 
{   
    int olderrno = errno;
    pid_t pid;

    pid = fgpid(jobs);
    // if (pid == 0)
    //     return;

    /* Just print something */
    Sio_puts("sigint runned: ");    /* But never print ? */
    Sio_putl((long) pid);
    Sio_puts("\n");

    kill(pid, SIGINT);


    errno = olderrno;    
    return;
}

When i remove if (pid == 0) return;, run the program. It will print "sigint runned: 0" in a infinite loop.

This is very different from what I expected. I am very confused. Any answer will be appreciated.

I’d love to know how to debug the signal problem in VsCode. If I can debug the signal I might be able to figure it out myself.

Solution

The problem that has been bothering me for a week is finally solved.HA.

I finally solved him by learning the advanced features of debug.

The tutorial(Really appreciate his video) :https://www.youtube.com/watch?v=xAW_pNBlfnI&list=PLZbQA0LtbR-275j6lHwmtZgKzOxfIkUmo&index=1&t=1133s

As for the problem itself, my system handles the SIGCHLD signal first, and then the SIGINT, which is inconsistent with what I’ve learned, and I’ve never been able to understand it. I take it for granted to think according to what I have learned, so I have been unable to solve it. In the end, practice is the answer to all questions, and it is really important to learn to debug well.

Thanks to all gays who enthusiastically gave suggestions.

Answered By – Alex_cpy

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published