How to set signal checking in loop?

2019-09-05 17:10发布

In createProcess(pid_t pidArray[]) function i create new process and if it's child i print it. But in while loop i everytime check killFlag, and my program no efficiant. How can i fix this issue.? Thank you for any help. In my program you can add process by pressing + or delete it by pressing - or just quit by pressing q.

This is my code:

#include <ncurses.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <signal.h> 
#include <string.h> 
#include <stdlib.h> 

bool printAllowed = false; 
bool killFlag = true; 
bool flag = false; 
int processesCount = 0; 
int currentProcessNumber = 0; 
static const char *colors[] = { "\x1B[0m", "\x1B[31m","\x1B[32m","\x1B[33m","\x1B[34m","\x1B[35m","\x1B[36m","\x1B[37m" }; 

struct sigaction printSignal, killSignal; 

void allowPrint(int sign){ 
  printAllowed = true; 
} 

void setKillFlag(int sign){ 
  killFlag = true; 
} 

int createProcess(pid_t pidArray[]){ 

  if(processesCount > 100) return 1; 

  pidArray[processesCount] = fork(); 
  processesCount++; 

  switch(pidArray[processesCount - 1]){ 

    case 0:{ 
      killFlag = false; 
      char buff[255]; 
      int colorNumber = (processesCount > 7)? 0 : processesCount; 
      sprintf(buff,"%sProcess %d || ", colors[colorNumber], processesCount); 
      while(!killFlag) { 
        usleep(10000); 
        if(printAllowed){ 
          for(int i = 0; i < strlen(buff); i++){ 
            if(killFlag) { return -1;}; 
            printf("%c", buff[i]); 
            refresh(); 
            usleep(50000); 
          } 
          printAllowed = false; 
          // signal to parent that process stop print
          kill(getppid(), SIGUSR2); 
        } 
      } 
      return -1; 
    } 

    case -1: printf("%sError!", colors[1]); return 1; 

    default:  return 1; 
  } 
} 

bool killProcess(pid_t pidArray[]){ 
  if (processesCount <= 0) return 1; 

  processesCount--; 
  // stop last child process
  kill(pidArray[processesCount], SIGUSR2); 
  waitpid(pidArray[processesCount], NULL, NULL); 
  // if the process that printing now stopped
  if (currentProcessNumber >= processesCount){ 
    currentProcessNumber = 0; // start from beginning
    flag = true;  // flag last process by number
    killFlag = true; // flag of end printing current process
  } 

  return 1; 
} 

int controlProcesses(pid_t pidArray[]){ 
  halfdelay(1); 
  switch((char)getchar()){ 
  case '=': return createProcess(pidArray); 
  case '-': return killProcess(pidArray); 
  case 'q': return 0; 
  default: return 1; 
  } 
} 

void killAllProcesses(pid_t pidArray[]){ 
  if(pidArray[--processesCount] != 0) 
    for( ;processesCount >= 0; processesCount--){ 
      kill(pidArray[processesCount],SIGUSR2); 
      waitpid(pidArray[processesCount],NULL,NULL); 
    } 
} 

int main(){ 

  initscr(); 
  clear(); 
  noecho(); 
  refresh(); 


  printSignal.sa_handler = allowPrint; 
  sigaction(SIGUSR1,&printSignal,NULL); 

  killSignal.sa_handler = setKillFlag; 
  sigaction(SIGUSR2,&killSignal,NULL); 

  pid_t pidArray[100]; 

  while(int i = controlProcesses(pidArray)) { 

    if(i == -1) return 0; 


    if(killFlag && processesCount > 0){  // if current process stop printing
      killFlag = false; 
      if(currentProcessNumber >= processesCount - 1) currentProcessNumber = 0; // if the number of current process is last, start from beginning
      else if(!flag) currentProcessNumber++; // else if last stopped process wasn't the last by number go to next process
      flag = false; 
      kill(pidArray[currentProcessNumber], SIGUSR1); // signal to child process start the printing
    } 
    refresh(); 
  } 
  // stop all child processes
  killAllProcesses(pidArray); 

  clear(); 
  endwin(); 

  return 0; 
}

标签: c linux signals
1条回答
Fickle 薄情
2楼-- · 2019-09-05 17:34

Your killFlags (and printAllowed) is wrongly declared. It should be declared

volatile sig_atomic_t killFlags, printAllowed;

The volatile qualifier is really important. Otherwise, the compiler would optimize by assuming killFlags can only be explicitly changed (it does not know that a signal handler could change it at any moment, so it could optimize by keeping that variable in a register, etc...).

Read carefully signal(7) man page.

If your loop is a polling event loop (probably based upon poll(2) ...) you might consider using the Linux specific signalfd(2) call.

查看更多
登录 后发表回答