#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <signal.h>
#include <elf.h>
#include <errno.h>
void checkIfExists(pid_t pid);
struct sigaction sig_4,sig_11,sig_12,old_sa12;
sigset_t new_mask;
sigset_t old_mask;
// Обработчики сигналов
void signal4_SIGILL(int sig) {
printf("Signal SIGILL 4 has been received from parent %d and my pid is %d \n",getppid(),getpid());
}
void signal12_SIGUSR2(int sig) {
printf("Signal SIGUSR2 12 has been received from parent %d and my pid is %d \n",getppid(),getpid());
}
void signal11_SIGSEGV(int sig) {
printf("Signal SIGSEGV 11 has been received from parent %d and my pid is %d \n",getppid(),getpid());
printf("Going to do some useless stuff to delay execution \n");
sleep(1);
printf("After perfoming stuff\n");}
int main()
{
pid_t pid;
printf("program start...\n");
pid = fork();
if (pid == -1 )
{
printf("error, process has no craete...\n");
return 1;
}
if (pid == 0)
{
printf("Child creation...\n");
memset (&sig_4, '\0', sizeof(sig_4)); // Выделяем место и заполняем нулями для структур
memset (&sig_11, '\0', sizeof(sig_11));
memset (&sig_12, '\0', sizeof(sig_12));
sig_4.sa_handler = &signal4_SIGILL; // Устанавливаем обработчик для сигнала 4
sig_4.sa_flags=SA_NODEFER; // Разрешаем вызов сигнала из его же обработчика
sig_11.sa_handler = &signal11_SIGSEGV;
sig_11.sa_flags=SA_NODEFER;
sig_12.sa_handler = &signal12_SIGUSR2;
sig_12.sa_flags = SA_NODEFER|SA_RESETHAND; // Устанавливаем стандартный обработчик после первого получения
if (sigaction(SIGILL, &sig_4, NULL) < 0) { // Устанавливаем новую структуру для определенного сигнала
perror ("sigaction"); // Если произошла ошибка
return 1;
}
if (sigaction(SIGSEGV, &sig_11, NULL) < 0) {
perror ("sigaction");
return 1;
}
if (sigaction(SIGUSR2, &sig_12,&old_sa12 ) < 0) {
perror ("sigaction");
return 1;
}
if (sigemptyset(&new_mask)) { // Заполняем структуру маски (нулями)
return 1;
}
if (sigaddset(&new_mask, SIGILL)) { // Добавляем в маску номер сигнала для блокировки
return 1;
}
printf("Trying to set mask for process \n"); // Устанавливаем маску для процесса
if (sigprocmask(SIG_BLOCK, &new_mask, NULL)) {
return 1;
}
// Данный участок кода для временного блокирования сигнала для процесса.
//printf("In masked section for signal SIGILL, trying to sleep \n");
//sleep(3);
//printf("In masked section for signal SIGILL, after sleep \n");
//if (sigprocmask(SIG_UNBLOCK, &new_mask, NULL)) {
//return 1;
//}
while(true) {};
printf("Child end ...\n");
}
else
{
sleep(2);
printf("i`m parеnt, id=%d\n",getpid());
sleep(1);
printf("starting to send signal...\n");
printf("send SIG_4\n");
if (kill(pid,4)<0){printf("send signal failed\n");} // Посылаем сигнал дочернему процессу
sleep(1); // Спим для задержки
printf("send SIG_11\n");
if (kill(pid,11)<0){printf("send signal failed\n");}
sleep(1);
printf("send second SIG_11\n");
if (kill(pid,11)<0){printf("send signal failed\n");}
sleep(1);
printf("send SIG_12\n");
if (kill(pid,12)<0){printf("send signal failed\n");} // Посылаем сигнал №12, в его обработчике устанавливем по умолчанию
sleep(1);
printf("send second SIG_12 after restoring to default handler\n");
if (kill(pid,12)<0){printf("send signal failed\n");} // Посылаем еще раз сигнал №12
sleep(1);
checkIfExists(pid);
printf("Sending signals and allowing to catch inside same handler\n");
printf("I am going to send a lot of requests to SIG11 to test handling signals in predefined handler\n");
printf("send again SIG_11\n");
if (kill(pid,11)<0){printf("send signal failed\n");}
checkIfExists(pid);
sleep(2);
/* for (int i=0;i<10;i++) {
if(kill(pid,11)<0){printf("send signal failed\n");}
}
*/
kill(pid,11);
if (kill(pid,9)<0){printf("send signal failed\n");} // Killing child process
sleep(1);
}
}
void checkIfExists(pid_t pid) {
kill(pid,0);
if(errno == ESRCH) {
printf("The pid or process does not exist.\n");
}
else {
printf("Process exists \n");
}
}
Собственно тут посылаю различные сигналы при определенных масках и обработчиках для каждого сигнала. Проблема в том что строчка printf("send again SIG_11\n");
if (kill(pid,11)<0){printf("send signal failed\n");}
не выполняется если перед этим был подан сигнал 12. В сигнале 12 стоят флаги sig_12.sa_flags = SA_NODEFER|SA_RESETHAND; если убрать SA_RESETHAND все работает, а если оставить только его, то тоже не работает. Смотрел вроде же SA_RESETHAND восстанавливает только для одного сигнала дефолтный обработчик.
Вывод в консоль следующий.