Chapter:C Signals Exercises

From Juneday education
Jump to: navigation, search

Use simple example

Download, compile and execute the following source code: ctrl-c.c.

Expand using link to the right to see a possible solution/answer.

$ curl -LJO https://raw.githubusercontent.com/progund/programming-with-c/master/signal/ctrl-c.c
$ gcc ctrl-c.c -o ctrl-c
$ ./ctrl-c 
....................................................................................................................

Terminate simple example

Try stopping the above program's execution?

Expand using link to the right to see a possible solution/answer.

Pressing control-c in the terminal will not do any good:

$ ./ctrl-c 
...........^CSIGINT (2) cuaght, will print this and continue afterwards
.......^CSIGINT (2) cuaght, will print this and continue afterwards
....^CSIGINT (2) cuaght, will print this and continue afterwards
...^CSIGINT (2) cuaght, will print this and continue afterwards

Press control-z in the terminal

$ ./ctrl-c 
.........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................^Z
[1]+  Stopped                 ./ctrl-c

The program have now stopped. From the above ([1]+ Stopped ./ctrl-c) we can see that the job number is 1. To terminate the program kill it, using it's job number:

kill %1

Terminate the program after three Ctrl-c

Count the number of times the user have pressed Ctrl-c. The third time the program shall terminate. Executing your program shall look (a bit like this):

$ ./ctrl-c3
......^CSIGINT (2) pressed 1 times, will print this and continue afterwards
....^CSIGINT (2) pressed 2 times, will print this and continue afterwards
.....^C[hesa@bartok tmp]$

Expand using link to the right to see a possible solution/answer.

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


void sighandler(int sig)
{
  static int int_counter;
  int_counter++;
  if (int_counter==3)
    {
      exit(0);
    }
  printf ("SIGINT (%d) pressed %d times, will print this and continue afterwards\n", sig, int_counter);
}

int
main(void)
{

  signal(SIGINT, sighandler); 
  
  while (1)
    {
      printf (".");
      fflush(stdout);
      usleep (100000);
    }

  return 0;
}

You can find the source code of this solution over at GitHub: ctrl-c3.c

Register a handler for SIGHUP (as well as for SIGINT)

Register to handle SIGHUP as well as SIGINT. You can use the same signal handler with a switch statement to handle to two signals differently. You don't have to anything fancy when handling SIGHUP - a print statement is enough.

Hint: to send SIGHUP to your program, assuming it is called two-signals, use pkill -HUP two-signals in a separate terminal.

Expand using link to the right to see a possible solution/answer.

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


void sighandler(int sig)
{
  static int int_counter;

  switch (sig) {
  case SIGINT:
    int_counter++;
    if (int_counter==3)
      {
        exit(0);
      }
    printf ("SIGINT (%d) pressed %d times,"
            "will print this and continue afterwards\n",
            sig, int_counter);
    break;
  case SIGHUP:
    printf ("SIGHUP (%d) pressed "
            "will print this and continue afterwards\n",
            sig);
    break;
  }
}

int
main(void)
{

  signal(SIGINT, sighandler); 
  signal(SIGHUP, sighandler); 
  
  while (1)
    {
      printf (".");
      fflush(stdout);
      usleep (100000);
    }

  return 0;
}

You can find the source code of this solution over at GitHub: two-signals.c

Send SIGSEGV to your program

Send SIGSEGV to your program (two-signals) by using pkill -SEGV two-signals in a separate terminal. What do you think will happen? How do you think the kernel (in your operating system) notifies your program if reading from a afaulty memory address?

Expand using link to the right to see a possible solution/answer.

Terminal 1:

$ ./two-signals 
.........................................................Segmentation fault (core dumped)

Terminal 2:

$ pkill -SEGV two-signals

When sending SIGSEGV to your program the built in signal handler is invoked and handles the signal as if the program read from a faulty memory address. This explains why the printout from your program is the same as when crashing due to a read from a faulty memory address.