c++ sigaction SIGXCPU, process don't stop

I have this code:
Code:
volatile sig_atomic_t got_usr1;

void sigxcpu_handler(int sig)
{ 
  got_usr1 = 1;
   kill( getpid(), SIGXCPU );
}

int main(void)
{
  
  //limit on cpu time
  struct rlimit vLimCPU;
  vLimCPU.rlim_cur = 1;
  vLimCPU.rlim_max = 1;
  setrlimit(RLIMIT_CPU, &vLimCPU);
  
  struct sigaction sa;
  
  got_usr1 = 0;
  
  sa.sa_handler = sigxcpu_handler;
  sa.sa_flags = 0;
  sigemptyset(&sa.sa_mask);
  
  if (sigaction(SIGXCPU, &sa, NULL) == -1) {
    perror("sigaction");
    exit(1);
  }
  
  while (!got_usr1) {
    printf("PID %d: working hard...\n", getpid());
    sleep(1);
  }
  
  printf("Done in by SIGXCPU!\n");
  
  return 0;
}
Why does the process not stop after one second? And why is sigxcpu_handler never called?
 
As far as I know sigaction(2) will not send a signal, but place the control structure to react to a signal. It means that your process is ready to receive the signal, but noone sends it. So while the process is running you have to send the signal from another terminal, for instance executing [cmd=]kill -s XCPU <pid>[/cmd] or change the code so that it will "manually" send a signal to itself, for instance with:

Code:
while (!got_usr1) {                                                                      
    printf("PID %d: working hard...\n", getpid());                                         
    sleep(1);                                                                              
                                                             
    [color="Red"]sigxcpu_handler( -1 );   [/color]                                                            
  }

In both ways, your process is going to loop, since in the signal handler you are delivering another signal, that will call back the signal handler, which will deliver another signal, and so on, so the process is not going to stop. I don't get why you are using such a signal scheme.
 
But in the FreeBSD System Calls Manual getrlimit(2) I read this: "When the soft cpu time limit is exceeded, a signal SIGXCPU is sent to the offending process."
 
Problem is in your while loop, both sleep() and printf() will cause your process to be put in "sleep" state until syscalls that these functions wrap around return, this will not use CPU time on your process.

So if you change it to something like:
Code:
while (!got_usr1) {
    1.234 / 9.876543;
}

This will fire up the SIGXCPU signal exactly after one second.
 
xnl96 said:
But in the FreeBSD System Calls Manual getrlimit(2) I read this: "When the soft cpu time limit is exceeded, a signal SIGXCPU is sent to the offending process."

Oops, sorry, I didn't notice that. However, as already explained, an I/O or sleep call will cause the CPU to be released, and therefore the time not to be "counted".
 
Back
Top