1

重複の可能性:
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;
}
4

0 に答える 0