3

I'm trying to learn how to catch sigterm for a larger assignment I have in class. I'm following the steps in this tutorial however it doesn't work for me. When I enter the command "kill [process id]" the sleep doesn't stop and just continues. I've tried kill both the child and parent IDs and nothing happens. Any ideas? Here's what I have:

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

volatile sig_atomic_t done = 0;

void term(int signum)
{
   printf("Caught!\n");
   done = 1;
}

int main(int argc, char *argv[])
{
    struct sigaction action;
    memset(&action, 0, sizeof(action));
    action.sa_handler = term;
    sigaction(SIGTERM, &action, NULL);

    int pid = getpid();
    int parentID = getppid();
    printf("PID is %d  and Parent is %d \n",pid, parentID);

    int loop = 0;
    while (!done)
    {
        printf("PID is %d  and Parent is %d \n",pid, parentID);
        int t = sleep(10);
        /* sleep returns the number of seconds left if
         * interrupted */
        while (t > 0)
        {
            printf("Loop run was interrupted with %d "
                   "sec to go, finishing...\n", t);
            t = sleep(t);
        }
        printf("Finished loop run %d.\n", loop++);
    }

    printf("done.\n");
    return 0;
}
Kenney
  • 9,003
  • 15
  • 21
user2466886
  • 205
  • 1
  • 3
  • 14
  • Although not an answer to your question, you shouldn't use functions that aren't re-entrant inside a signal handler. _printf_ is one of them. This SO [question/answer](http://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler) might be helpful to look at – Michael Petch Nov 21 '15 at 21:15
  • WHat happens if you explicitly use the signal number (TERM) with the `kill` on the child process. As in `kill -TERM ` where `` is the ID of the child process. – Michael Petch Nov 21 '15 at 21:40
  • My best guess though is - when you did that tutorial you weren't aware that you are suppose to open two terminal sessions. One to run the program, and second terminal to issue the `kill` command. My guess is you ran your program and in the same terminal you issued the kill command. Doing it the way the tutorial is suggesting requires _TWO_ active terminal sessions. – Michael Petch Nov 21 '15 at 21:49
  • 1
    It is not safe to call `printf` in a signal handler. See: [`man signal-safety`](https://man7.org/linux/man-pages/man7/signal-safety.7.html) – ceving Jul 13 '21 at 15:55

1 Answers1

1

Works fine:

> cat > sig.c    # paste your code
> gcc sig.c
> ./a.out &
[1] 20549
PID is 20549  and Parent is 15574
PID is 20549  and Parent is 15574
> kill 20549
Caught!
Loop run was interrupted with 1 sec to go, finishing...
> Finished loop run 0.
done.
>
[1]    Done                          ./a.out
Kenney
  • 9,003
  • 15
  • 21
  • It doesn't work on my mac. My program just moves to the next line. – user2466886 Nov 21 '15 at 21:18
  • What do you mean, *"moves to the next line"*? Are you running your process in the background? Or do you have 2 terminals open, one running your program, and the other with a shell commandline? – Kenney Nov 21 '15 at 21:21
  • I literally mean the cursor moves to the line beneath the kill command (the same response if I had just hit enter). No I'm not running anything in the background or have 2 terminals opens. For some reason the steps in the tutorial don't work for me – user2466886 Nov 21 '15 at 21:26
  • So you type `kill `, press enter, and all that happens is the cursor moves to the next line? In what shell are you entering that? – Kenney Nov 21 '15 at 21:38
  • I tried it in bash since that's what my class uses – user2466886 Nov 21 '15 at 21:43
  • What do you type to start your program? – Kenney Nov 21 '15 at 21:48
  • I compile using gcc -o samp samp.c and then run it as ./samp – user2466886 Nov 21 '15 at 21:50
  • @user2466886 add an & (ampersand) on the end, so it should be `./samp &` that puts the program in the background and allows you to issue new commands at the shell (like kill) – Michael Petch Nov 21 '15 at 21:52
  • In that case you should open a second bash window and type the `kill` command there. – Kenney Nov 21 '15 at 21:52
  • The ampersand did it, why did it need to be a background process? – user2466886 Nov 21 '15 at 22:01
  • 3
    @user2466886 Without the ampersand the program is a *foreground process* and takes over the I/O for the terminal. You can type (and the tty device will echo the keystrokes) but the input line just accumulates in the program's *stdin* file. Running the program in the background, the shell retains control of the terminal and will read (and execute) new commands. – luser droog Nov 21 '15 at 22:15