setrlimit non è affidabile?

Sto cercando di usare setrlimit() per setrlimit() la quantità di tempo che un processo richiede. Tuttavia non sembra funzionare quando eseguo determinate operazioni come printf() .

Ecco un programma di test che illustra il problema:

 #include  #include  int main(void) { int i; struct rlimit limit; limit.rlim_cur = 3; limit.rlim_max = 3; // send SIGKILL after 3 seconds setrlimit(RLIMIT_CPU, &limit); // doesn't get killed for(i=0; i<1000000; i++) printf("%d",i); return 0; } 

Comunque se sostituisco il ciclo for con una routine diversa come i naive fibonacci:

 int fib(int n) { if(n<=1) return 1; return fib(n-1)+fib(n-2); } int main(void) { ... fib(100); ... } 

Funziona perfettamente. Cosa sta succedendo qui? setrlimit() semplicemente inaffidabile?

Il limite della CPU è un limite per i secondi della CPU piuttosto che per il tempo trascorso. La CPU seconds è in pratica il numero di secondi in cui la CPU è stata utilizzata e non si riferisce necessariamente direttamente al tempo trascorso.

Quando fai la chiamata di fib , martella la CPU in modo che il tempo trascorso e il tempo di CPU siano vicini (la maggior parte del tempo di processo viene speso usando la CPU). Non è questo il caso della stampa poiché la maggior parte del tempo viene spesa in I / O.

Quindi, ciò che sta accadendo nel tuo caso particolare è che il rlimit è impostato, ma non stai usando i tre secondi di tempo della CPU prima che il processo finisca.

La modifica del main come segue causa la consegna del segnale sul mio sistema:

 int main(void) { int i; struct rlimit limit; limit.rlim_cur = 3; limit.rlim_max = 3; // send SIGKILL after 3 seconds setrlimit(RLIMIT_CPU, &limit); while (1) { // Run "forever". for(i=0; i<100000; i++) { printf("%d\n",i); } fib(30); // some CPU-intensive work. } return 0; } 

Quando hai time con Linux, vedi:

 : (much looping). 52670 52671 52672 52673 52674 Killed real 0m18.719s user 0m0.944s sys 0m2.416s 

In quel caso, ci sono voluti quasi 20 secondi di tempo trascorso ma la CPU era in uso solo per 3,36 secondi (utente + sys).

Il rlimit viene posizionato sul tempo della CPU, non sul tempo della parete. A seconda di dove sta andando il tuo output, il tuo programma potrebbe trascorrere la maggior parte del tempo in attesa sul dispositivo di output. Mentre lo fa, non consuma il tempo della CPU. Quindi il programma può durare più di 3 secondi, ma se si controlla l’utilizzo della CPU ( ps up $PID e guarda sotto TIME ) verrà mostrato meno di 3 secondi utilizzati.