[comp.bugs.4bsd] Programs can thwart cpu time limit

heather@CS.UCLA.EDU (05/24/87)

I believe that the following behavior is a bug:

	I write a program that specifies a hard and a soft cpu time
	limit using the setrlimit() system call.  I also use
	signal() to catch SIGXCPU signals (cpu time exceeded).
	What I expect to happen, based on the following quotes
	from the setrlimit manual page, is for the signal handler 
	to get called when the soft limit is exceeded and for the 
	program to be killed by the system when the hard limit is 
	exceeded.  

(Quotes from 'man 2 setrlimit')

     "A resource limit is specified as a soft limit and a hard
     limit.  When a soft limit is exceeded a process may receive
     a signal (for example, if the cpu time is exceeded), but it
     will be allowed to continue execution until it reaches the
     hard limit (or modifies its resource limit). ... "

     "A file I/O operation that would create a file that is too
     large will cause a signal SIGXFSZ to be generated; this nor-
     mally terminates the process, but may be caught.  When the
     soft cpu time limit is exceeded, a signal SIGXCPU is sent to
     the offending process." 

(End quote)

	Instead what happens is that the the signal handler gets 
	called once every 5 seconds from the time I hit the soft 
	limit to the time I hit the hard limit (see line 144 of 
	kern_clock.c for 5 second figure-- why isn't this documented).  
	At that point, the signal handler is constantly called.  I 
	have attached a program which demonstrates that behavior
	after my signature.

	In addition, I found that a process could easily thwart an 
	imposed cpu limit by simply declaring a signal handler for SIGXCPU,
	and doing all the calculations it wants to do in the
	signal handler itself.  For example, instead of returning
	from the signal handler printsig() in the program below,
	I placed the line 'while (1);'.  I found that program
	continued running indefinitely while accumulating cpu time.

	Does anyone have the fix to this bug?  Or, I should ask first,
	is this not really a bug but rather a misunderstanding on my
	part about how the system is supposed to work?  I'll wait
	for a while for a response and if no one has a fix, I'll
	try to fix it myself.

	Another question:  I originally looked into the kernel cpu 
	resource limitation code because of an unrelated problem:  Users 
	on our system have set very high cpu time limits (using csh) 
	for programs that they want to run, yet find that their programs 
	occassionally get killed with "Cputime limit exceeded" long 
	before the limit they set could have passed.  For example, setting
	a limit of 1,000,000 seconds should allow a program to run
	> 11 days but users have reported that their programs have
	been killed within a day.  The limitation is set like this
	within the csh:

	(limit -h cputime 1000000; limit cputime 1000000; <program>)

	Both hard and soft limits are the same and the program does
	not try to catch SIGXCPU so the problem is really unrelated
	to the above bug description.  Has anyone else experienced 
	problems like this?

					Heather Burris
					Programmer, UCLA
	
	

/*	program whose signal handler will get called indefinitely */

#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>

printsig()
	{
	struct rlimit r;

	getrlimit(RLIMIT_CPU, &r);
/*	The following will print hardlimit, softlimit pairs of
 *		(20, 10), (20, 15) and (20,20) 5 seconds apart and
 *		then will quickly and constantly print (20,20)
 *		indefinitely.
 */
	fprintf(stderr, "Received signal, hardlimit %d, softlimit %d\n",
		r.rlim_max, r.rlim_cur);
	}

main(argc, argv	)
	int argc;	
	char **argv;
	{
	struct rlimit r;

	r.rlim_cur = 5;
	r.rlim_max = 20;
	setrlimit(RLIMIT_CPU, &r);
	getrlimit(RLIMIT_CPU, &r);
	fprintf(stderr, "Hardlimit %d, softlimit %d\n", r.rlim_max, r.rlim_cur);
	signal(SIGXCPU, printsig);
	while(1);
	}

/*	End of program */

larry@ecf.UUCP (05/26/87)

In article <6208@shemp.UCLA.EDU> heather@CS.UCLA.EDU (Heather Burris) writes:
>
>I believe that the following behavior is a bug:
>
>	I write a program that specifies a hard and a soft cpu time
>	limit using the setrlimit() system call.  I also use
>	signal() to catch SIGXCPU signals (cpu time exceeded).
>	...
>	Instead what happens is that the the signal handler gets 
>	called once every 5 seconds from the time I hit the soft 
>	limit to the time I hit the hard limit (see line 144 of 
>	kern_clock.c for 5 second figure-- why isn't this documented).  
>	At that point, the signal handler is constantly called.

Yup, I think that is a bug also.  We do enforce resource limits on our
student who are the world's most adept at writing programs with infinite
loops.  The following trivial fix will cause the program to die when it
exceeds the hard limit.

*** /tmp/,RCSt1024359	Tue May 26 09:02:48 1987
--- kern_clock.c	Wed Nov  5 11:35:10 1986
***************
*** 4,10 ****
   * specifies the terms and conditions for redistribution.
   *
   *	@(#)kern_clock.c	7.1 (Berkeley) 6/5/86
!  * $Header: kern_clock.c,v 1.2 86/10/21 14:55:15 larry Exp $
   */
  
  #include "../machine/reg.h"
--- 4,10 ----
   * specifies the terms and conditions for redistribution.
   *
   *	@(#)kern_clock.c	7.1 (Berkeley) 6/5/86
!  * $Header: kern_clock.c,v 1.3 86/11/05 11:35:05 larry Exp $
   */
  
  #include "../machine/reg.h"
***************
*** 146,151 ****
--- 146,154 ----
  			if (u.u_rlimit[RLIMIT_CPU].rlim_cur <
  			    u.u_rlimit[RLIMIT_CPU].rlim_max)
  				u.u_rlimit[RLIMIT_CPU].rlim_cur += 5;
+ 			else
+ 				/* kill the proc if hard cpu limit exceeded */
+ 				psignal(u.u_procp, SIGKILL);
  		}
  		if (timerisset(&u.u_timer[ITIMER_PROF].it_value) &&
  		    itimerdecr(&u.u_timer[ITIMER_PROF], tick) == 0)

Larry Philps	Engineering Computing Facility	University of Toronto
NEW PATH:   larry@ecf.toronto.edu
USENET:     {linus, ihnp4, allegra, decvax, floyd}!utcsri!ecf!larry
CSNET:      larry@Toronto
ARPA:       larry%Toronto@CSNet-Relay
BITNET:     larry@ecf.utoronto.BITNET