重複の可能性:
sigaction を使用した複数のシグナル ハンドラーの登録
sigaction 関数を使用してプロセスに複数のシグナル ハンドラを登録するにはどうすればよいですか。次のコードを試しました
struct sigaction action1;
action1.sa_handler = signal_catcher_monitor_1;
sigaction(SIGUSR1,&action1,NULL);
struct sigaction action2;
action2.sa_handler = signal_catcher_monitor_2;
sigaction(SIGUSR2,&action2,NULL);
ただし、シグナル ハンドラが機能していないようです。シグナルハンドラの 1 つが一度呼び出された後、それらは呼び出されません。
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <signal.h>
#include <cstdio>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define NUM_SENDER_PROCESSES 3
#define NUM_HANDLER_PROCESSES 4
#define NUM_SIGNAL_REPORT 10
#define MAX_SIGNAL_COUNT 100000
using namespace std;
volatile int *usrsig1_handler_count;
volatile int *usrsig2_handler_count;
volatile int *usrsig1_sender_count;
volatile int *usrsig2_sender_count;
volatile int *lock_1;
volatile int *lock_2;
volatile int *lock_3;
volatile int *lock_4;
volatile int *lock_5;
volatile int *lock_6;
//Used only by the monitoring process
volatile int monitor_count;
volatile int usrsig1_monitor_count;
volatile int usrsig2_monitor_count;
double time_1[NUM_SIGNAL_REPORT];
double time_2[NUM_SIGNAL_REPORT];
//Used only by the main process
int total_signal_count;
//For shared memory
int shmid;
const int shareSize = sizeof(int) * (10);
double timestamp() {
struct timeval tp;
gettimeofday(&tp, NULL);
return (double)tp.tv_sec + tp.tv_usec / 1000000.;
}
pid_t senders[NUM_SENDER_PROCESSES];
pid_t handlers[NUM_HANDLER_PROCESSES];
pid_t reporter;
void terminate_processes() {
//Kill the child processes
int status;
cout << "Time up terminating the child processes" << endl;
for(int i=0; i<NUM_SENDER_PROCESSES; i++) {
kill(senders[i],SIGKILL);
}
for(int i=0; i<NUM_HANDLER_PROCESSES; i++) {
kill(handlers[i],SIGKILL);
}
kill(reporter,SIGKILL);
//Wait for the child processes to finish
for(int i=0; i<NUM_SENDER_PROCESSES; i++) {
waitpid(senders[i], &status, 0);
}
for(int i=0; i<NUM_HANDLER_PROCESSES; i++) {
waitpid(handlers[i], &status, 0);
}
waitpid(reporter, &status, 0);
}
int main(int argc, char *argv[]) {
void signal_catcher_1(int);
void signal_catcher_2(int);
void signal_catcher_int(int);
void signal_catcher_monitor_1(int);
void signal_catcher_monitor_2(int);
void signal_catcher_main(int);
if(argc != 2) {
cout << "Required parameters missing. " << endl;
cout << "Option 1 = 1 which means run for 30 seconds" << endl;
cout << "Option 2 = 2 which means run until 100000 signals" << endl;
exit(0);
}
int option = atoi(argv[1]);
pid_t pid;
if(option == 2) {
if(signal(SIGUSR1, signal_catcher_main) == SIG_ERR) {
perror("1");
exit(1);
}
if(signal(SIGUSR2, signal_catcher_main) == SIG_ERR) {
perror("2");
exit(1);
}
} else {
if(signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
perror("1");
exit(1);
}
if(signal(SIGUSR2, SIG_IGN) == SIG_ERR) {
perror("2");
exit(1);
}
}
if(signal(SIGINT, signal_catcher_int) == SIG_ERR) {
perror("3");
exit(1);
}
///////////////////////////////////////////////////////////////////////////////////////
////////////////////// Initializing the shared memory /////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
cout << "Initializing the shared memory" << endl;
if ((shmid=shmget(IPC_PRIVATE,shareSize,IPC_CREAT|0660))< 0) {
perror("shmget fail");
exit(1);
}
usrsig1_handler_count = (int *) shmat(shmid, NULL, 0);
usrsig2_handler_count = usrsig1_handler_count + 1;
usrsig1_sender_count = usrsig2_handler_count + 1;
usrsig2_sender_count = usrsig1_sender_count + 1;
lock_1 = usrsig2_sender_count + 1;
lock_2 = lock_1 + 1;
lock_3 = lock_2 + 1;
lock_4 = lock_3 + 1;
lock_5 = lock_4 + 1;
lock_6 = lock_5 + 1;
//Initialize them to be zero
*usrsig1_handler_count = 0;
*usrsig2_handler_count = 0;
*usrsig1_sender_count = 0;
*usrsig2_sender_count = 0;
*lock_1 = 0;
*lock_2 = 0;
*lock_3 = 0;
*lock_4 = 0;
*lock_5 = 0;
*lock_6 = 0;
cout << "End of initializing the shared memory" << endl;
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////// End of initializing the shared memory ///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////Registering the signal handlers///////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
cout << "Registering the signal handlers" << endl;
for(int i=0; i<NUM_HANDLER_PROCESSES; i++) {
if((pid = fork()) == 0) {
if(i%2 == 0) {
struct sigaction action;
action.sa_handler = signal_catcher_1;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGUSR1,&action,NULL);
if(signal(SIGUSR2, SIG_IGN) == SIG_ERR) {
perror("2");
exit(1);
}
} else {
if(signal(SIGUSR1 ,SIG_IGN) == SIG_ERR) {
perror("1");
exit(1);
}
struct sigaction action;
action.sa_handler = signal_catcher_2;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGUSR2,&action,NULL);
}
if(signal(SIGINT, SIG_DFL) == SIG_ERR) {
perror("2");
exit(1);
}
while(true) {
pause();
}
exit(0);
} else {
//cout << "Registerd the handler " << pid << endl;
handlers[i] = pid;
}
}
cout << "End of registering the signal handlers" << endl;
/////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////End of registering the signal handlers //////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////Registering the monitoring process //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
cout << "Registering the monitoring process" << endl;
if((pid = fork()) == 0) {
struct sigaction action1;
action1.sa_flags = 0;
action1.sa_handler = signal_catcher_monitor_1;
sigemptyset(&action1.sa_mask);
sigaction(SIGUSR1,&action1,NULL);
struct sigaction action2;
action2.sa_flags = 0;
sigemptyset(&action2.sa_mask);
action2.sa_handler = signal_catcher_monitor_2;
sigaction(SIGUSR2,&action2,NULL);
if(signal(SIGINT, SIG_DFL) == SIG_ERR) {
perror("2");
exit(1);
}
while(true) {
pause();
}
exit(0);
} else {
cout << "Monitor's pid is " << pid << endl;
reporter = pid;
}
cout << "End of registering the monitoring process" << endl;
/////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////End of registering the monitoring process////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
//Sleep to make sure that the monitor and handler processes are well initialized and ready to handle signals
sleep(5);
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////Registering the signal generators///////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
cout << "Registering the signal generators" << endl;
for(int i=0; i<NUM_SENDER_PROCESSES; i++) {
if((pid = fork()) == 0) {
if(signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
perror("1");
exit(1);
}
if(signal(SIGUSR2, SIG_IGN) == SIG_ERR) {
perror("2");
exit(1);
}
if(signal(SIGINT, SIG_DFL) == SIG_ERR) {
perror("2");
exit(1);
}
srand(i);
while(true) {
int signal_id = rand()%2 + 1;
if(signal_id == 1) {
killpg(getpgid(getpid()), SIGUSR1);
while(__sync_lock_test_and_set(lock_4,1) != 0) {
}
(*usrsig1_sender_count)++;
*lock_4 = 0;
} else {
killpg(getpgid(getpid()), SIGUSR2);
while(__sync_lock_test_and_set(lock_5,1) != 0) {
}
(*usrsig2_sender_count)++;
*lock_5=0;
}
int r = rand()%10 + 1;
double s = (double)r/100;
sleep(s);
}
exit(0);
} else {
//cout << "Registered the sender " << pid << endl;
senders[i] = pid;
}
}
//cout << "End of registering the signal generators" << endl;
/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////End of registering the signal generators///////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
//Either sleep for 30 seconds and terminate the program or if the number of signals generated reaches 10000, terminate the program
if(option = 1) {
sleep(90);
terminate_processes();
} else {
while(true) {
if(total_signal_count >= MAX_SIGNAL_COUNT) {
terminate_processes();
} else {
sleep(0.001);
}
}
}
}
void signal_catcher_1(int the_sig) {
while(__sync_lock_test_and_set(lock_1,1) != 0) {
}
(*usrsig1_handler_count) = (*usrsig1_handler_count) + 1;
__sync_lock_release(lock_1);
}
void signal_catcher_2(int the_sig) {
while(__sync_lock_test_and_set(lock_2,1) != 0) {
}
(*usrsig2_handler_count) = (*usrsig2_handler_count) + 1;
__sync_lock_release(lock_2);
}
void signal_catcher_main(int the_sig) {
while(__sync_lock_test_and_set(lock_6,1) != 0) {
}
total_signal_count++;
*lock_6 = 0;
}
void signal_catcher_int(int the_sig) {
for(int i=0; i<NUM_SENDER_PROCESSES; i++) {
kill(senders[i],SIGKILL);
}
for(int i=0; i<NUM_HANDLER_PROCESSES; i++) {
kill(handlers[i],SIGKILL);
}
kill(reporter,SIGKILL);
exit(3);
}
void signal_catcher_monitor_1(int the_sig) {
cout << " Monitor 1 " << endl;
}
void signal_catcher_monitor_2(int the_sig) {
cout << "Monitor 2 " << endl;
}