All about Linux signals

Sending signals


Sending signal from keyboard


There are two special key combinations that can be used in a terminal to send a signal to the running application:
  • CTRL-C - sends SIGINT which default action is to terminate the application.
  • CTRL-\ - sends SIGQUIT which default action is to terminate the application dumping core.
  • CTRL-Z - sends SIGSTOP that suspends the program.

kill()


The simplest way to send a signal to the process is to use kill(2). It takes two arguments: pid (PID of the process) and sig (the signal to send). Although the function has a simple interface it's worth to read the manual page because there are few more things we can do than just sending a signal to a process:
  • The pid can be 0, the signal will be sent to all processes in the process group.
  • The pid can be -1, the signal is sent to every process you have permission to send signals except init and system processes (you won't kill system threads).
  • The pid can be less than -1 to send signal to all processes in the process group whose ID is -pid.
  • You can check is a process exists sending signal 0. Nothing is really sent, but the kill(2) return value will be as if it sent a signal, so if it's OK it means that the process exists.

Sending signals to yourself


There are two standard function that will help you to send signals to yourself:
  • raise(3) - Just send the specified signal to yourself, but if it's a multithreaded program it sends the signal to the thread, not the process.
  • abort(3) - Sends SIGABRT, but before that it will unblock this signal, so this function works always, you don't need to bother about unblocking this signal. It will also terminates you program even if you have handler for SIGABRT by restoring the default signal handler and sending the signal again. You can prevent it as was mentioned in signal handling chapter.

Sending data along with signal - sigqueue()


The sigqueue(2) function works very similar to kill(2) but is has a third argument of type const union sigval which can be used to send an integer value or a pointer that can be read in the signal handler if it reads the siginfo_t argument. If you use this function instead of 32) the handler can distinguish this with the si_code field because it will have SI_QUEUE value.

Comments

Hello, Thank you for good

Hello, Thank you for good article. Is it possible to give permission of other user program to send signal to my process ? If yes, then how to do this ?

I don't think it's possible.

I don't think it's possible.

Restarting system calls

"It's not specified which calls are restarted" - says the last paragraph. It is very much specified, on the signal(7) man page.

very useful and readable blog about Unix signals

Unix signals is a deep and interesting topic. For example, the signal() function is either referring to the version in the C library or the version in the operating system. The topic of signals has a rich history as part of Unix.

Thanks

I just want to say thank you , I was googling about what happens to signals handlers when I fork() and you blog showed up. thanks

Ctrl+Z Signal

CTRL-Z - sends SIGTSTP

Hi, typo jerk here

Hi, typo jerk here again: page3: Moreover, it lack's features -> lacks why the signal was send -> sent page5: signals like SIGPIPE, SIGUSR1, SIGUSR1 -> SIGUSR2 signal i exits -> it This program read from it's -> reads, its Additionally when SIGUSR1 -> Additionally, when [missing comma] I hope you really, truly don't consider this as some kind of personal attack.

i love type jerk!

typos suck! combat them!

Thanks. I don't consider it

Thanks. I don't consider it as an attack :) Some of them are just caused by the fact that English is not my native language.

I was looking for linux

I was looking for linux programming tutorial and i found this blog . keep good work.

Great write-up

Great write-up; thanks for the information.

Signals - That's not everything

I wouls suggest the reading of "Advanced Programming in the Unix Environment". It does not address signals with threads, but it is the most extensive explanation of signal handling. It treats also long jumps to remove races in signal handling.

Problem regarding signals.

Hi I have written a sample program to understand signal handling. signal1.c
#include 
#include 
/* for random() stuff */
#include 
#include 
#include 
#include 

void
termination_handler (int signum)
{
  struct temp_file *p;
 int err;
  printf("\nTerminated\n");
		sleep(10); 
}

int
main (void)
{

	int shmfd,*shared_msg, pid;
	struct sigaction new_action, old_action;
	int shared_seg_size = (1 * sizeof(int));
	//shm operations
	shmfd = shm_open("/shm_sumit",O_CREAT|O_RDWR|O_EXCL,S_IRWXU | S_IRWXG);
	if (shmfd < 0) {
	        perror("In shm_open()");
        	exit(1);
    	}

	ftruncate(shmfd, shared_seg_size);
	shared_msg = (int *)mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
	if (shared_msg == NULL) {
	        perror("In mmap()");
        	exit(1);
    	}

        pid = getpid();
        *shared_msg = pid; 

  /* Set up the structure to specify the new action. */
  new_action.sa_handler = termination_handler;
  sigemptyset (&new_action.sa_mask);
  new_action.sa_flags = SA_NODEFER;

    sigaction (SIGUSR1, &new_action, NULL);
     //while(1)
{
   sleep(10);
}
	/*if (shm_unlink("/shm_sumit") != 0) {
	        perror("In shm_unlink()");
        	exit(1);
    	}*/

}



signal2.c


#include 
#include 
#include 
void
termination_handler (int signum)
{
  struct temp_file *p;
  printf("\nTerminated");
}

int
main (void)
{
	int shmfd,*shared_msg, pid;
    struct sigaction new_action, old_action;
    int shared_seg_size = (1 * sizeof(int));
    //shm operations
    shmfd = shm_open("/shm_sumit",O_RDWR,S_IRWXU | S_IRWXG);
    shared_msg = (int *)mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
    printf(" Process id of sigtest1 = %d\n",*shared_msg);
 kill(*shared_msg,SIGUSR1);
 kill(*shared_msg,SIGUSR1);
 kill(*shared_msg,SIGUSR1);
 kill(*shared_msg,SIGUSR1);
 kill(*shared_msg,SIGUSR1);
	
	sleep(1);
	if (shm_unlink("/shm_sumit") != 0) {
        perror("In shm_unlink()");
        exit(1);
    }

}
here sigtest2.c send SIGUSR1 to sigtest1.c 5 times, but the string "Terminated " gets printed sometimes 2 times and sometimes 5 times. why is this printing behavior inconsistent??

Hi, because while handling

Hi, because while handling the signal it wont be handle the signal of same type . you can check this by remove the sleep(10) in sigtest1.c . It will work fine.