Signal of communication between Linux threads

Posted by rubberjohn on Mon, 04 Oct 2021 23:38:51 +0200

1. Signal of communication between Linux threads

Under linux, each process has its own signal mask. This signal mask specifies which signal is blocked and which will not be blocked. It is usually handled by calling sigmask. At the same time, each process also has its own signal action. This behavior set specifies how to process the signal. Usually, it calls the signal action to process it.

2. Signal installation function

	int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);

Function:
The specified signal number to set the signal processing function.

Parameters:
signum: signal number.
act: pointer to an instance of the structure sigaction.
oldact: used to save the original signal processing. It can be NULL.

Return value:
Success: 0.
Failed: - 1.

3. Add all signals to the signal set function

	int sigfillset(sigset_t * set);

Function:
sigfillset() is used to initialize the parameter set signal set, and then add all signals to this signal set.

Parameters:
Set: the address identified by the signal set. You can operate the signal set later.

Return value:
Success: 0.
Failed: - 1.

4. Add a signal to the signal set function

	int sigaddset(sigset_t *set, int signum);

Function:
Add a new signal to this signal set.

Parameters:
Set: the address identified by the signal set. You can operate the signal set later.
signum: signal number.

Return value:
Success: 0.
Failed: - 1.

5. Initialize the signal set function

	int sigemptyset(sigset_t *set);

Function:
Initialize the signal set.

Parameters:
Set: the address identified by the signal set. You can operate the signal set later.

Return value:
Success: 0.
Failed: - 1.

6. Send signal function to thread

	int pthread_kill(thread_t tid, int sig);

Function:
Send a signal to the thread.

Parameters:
tid: thread ID.
sig: signal number.

Return value:
Success: 0.
Failed: - 1.

7. Change or check the signal mask function of the calling thread

	int pthread_sigmask(int how, const sigset_t *act, sigset_t *oldact);

Function:
Change or check the semaphore mask of the calling thread.

Parameters:
how: add or delete or replace set to the current signal mask.
act: signal shielding word.
oldact: NULL.

how Description:
SIG_BLOCK: the result set is the union of the current set parameter set (add the signal in the parameter set to the signal mask word)
SIG_UNBLOCK: the result set is the difference set of the current set parameter set (set the signal mask word as the signal in the parameter set)
SIG_SETMASK: the result set is the set pointed by the parameter set (the signal in the parameter set is deleted from the signal mask word)

Return value:
Success: 0.
Failed: - 1.

8. Reference code:

//=============================================================================
// File Name    : thread_signal.c
// Author       : FengQQ
//
// Description: signal
// Annotation   : 
//
//	int pthread_kill(pthread_t thread,int sig);
//	Send a sig signal to the thread. 0 is returned for success and error code is returned for failure
//
//	int sigaction(int signum,const truct sigaction *act,struct sigaction *oldact);
//	Set the processing function for the signal signum, which is specified in sigaction
//	act.sa_mask signal mask word
//	act.sa_handler signal set handler	
//
//	int pthread_sigmask(int how,const sigset_t *set,sigset_t *oldset);
//	Multithreaded signal masking function
//	how = SIG_BLOCK: add set to the current signal mask, where set represents the signal group to unblock.
//	SIG_UNBLOCK: deletes set from the current signal mask, where set indicates the signal group to unblock.
//	SIG_SETMASK: replace the current signal mask with set, where set represents the new signal mask.
//	In multithreading, the current semaphore mask of a new thread inherits the semaphore mask of the thread that created it
//
// Created by FengQQ. 2020-10-05
//=============================================================================
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>

//-------------Signal callback function 1-----------------
void sig_handler1(int arg)
{
	printf("pthread1 get signal\r\n");
	return;
}
//-------------Signal callback function 2-----------------
void sig_handler2(int arg)
{
	printf("pthread2 get signal\r\n");
	return;
}
//---------------Thread function 1------------------
void *pthread1_callback(void *arg)
{
	struct sigaction act;
	
	printf("new pthread 1\r\n");
	
	memset(&act,0,sizeof(act));						//Fill the memory space of act with 0
	sigaddset(&act.sa_mask,SIGQUIT);				//Add a signal to the signal set
	act.sa_handler = sig_handler1;
	sigaction(SIGQUIT,&act,NULL);					//Query or set signal processing mode
	pthread_sigmask(SIG_BLOCK,&act.sa_mask,NULL);
	sleep(2);
}
//---------------Thread function 2------------------
void *pthread2_callback(void *arg)
{       
	struct sigaction act;
	
	printf("new pthread 2\r\n");      

	memset(&act,0,sizeof(act));					//Fill the memory space of act with 0	
	sigaddset(&act.sa_mask,SIGQUIT);			//Add a signal to the signal set
	act.sa_handler = sig_handler2;	
	sigaction(SIGQUIT,&act,NULL);				//Query or set signal processing mode
	
	//pthread_sigmask(SIG_BLOCK,&act.sa_mask,NULL);
	sleep(2);
}

int main(int argc,char *argv[])
{
	int ret;
	int signal_value;
	pthread_t ptid1,ptid2;
	
	ret = pthread_create(&ptid1,NULL,pthread1_callback,NULL);
	if(ret != 0)
	{
		printf("create new pthread1 failed...\r\n");
		return -1;
	}	
	ret = pthread_create(&ptid2,NULL,pthread2_callback,NULL);
	if(ret != 0)
	{
		printf("create new pthread2 failed...\r\n");
		return -1;
	}
	
	sleep(1);
	
	signal_value = pthread_kill(ptid1,SIGQUIT);
	if(signal_value != 0)
	{
		printf("send signal to thread1 failed...\r\n");
	}
	
	signal_value = pthread_kill(ptid2,SIGQUIT);
	if(signal_value != 0)
	{
		printf("send signal to thread2 failed...\r\n");
	}	
	
	ret  = pthread_join(ptid1,NULL);
	if(ret != 0)
	{
		printf("pthread1 join failed...\r\n");
	}	
	ret  = pthread_join(ptid2,NULL);
	if(ret != 0)
	{
		printf("pthread2 join failed...\r\n");
	}
	
	return 0;
}

Topics: Linux