Bug 27262

Summary: process won't be terminated after CPUTIME exceeded
Product: Base System Reporter: in <in>
Component: kernAssignee: Andre Oppermann <andre>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 5.0-CURRENT   
Hardware: Any   
OS: Any   

Description in 2001-05-11 05:10:00 UTC
process which exceeds CPUTIME limit by setrlimit()
will not receive signal SIGXCPU and terminate.

Fix: 

unknown
How-To-Repeat: 
/*-
 * this program should be terminated after 2 secs,
 */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>

int
main(argc, argv)
     int argc;
     char *argv[];
{
        struct rlimit rlp;
        rlp.rlim_cur = 2;
        rlp.rlim_max = 2;
        setrlimit(RLIMIT_CPU, &rlp);
        while( 1 )
                ;
}
Comment 1 Peter Pentchev 2001-05-11 10:18:53 UTC
On Fri, May 11, 2001 at 12:00:52PM +0800, in@amalea.org wrote:
> 
> >Number:         27262
> >Category:       kern
> >Synopsis:       process won't be terminated after CPUTIME exceeded
> >Originator:     in@amalea.org
> >Release:        FreeBSD 5.0-CURRENT i386
> >Organization:
> International Amalea Organization
> >Environment:
> System: FreeBSD dns.amalea.org 5.0-CURRENT FreeBSD 5.0-CURRENT #0: Mon May 7 22:33:41 CST 2001 in@dns.amalea.org:/usr/obj/usr/src/sys/GENERIC i386
> 
> 
> 	CPU: Pentium III/Pentium III Xeon/Celeron (733.36-MHz 686-class CPU)
> 	FreeBSD 5.0-CURRENT i386
> 
> >Description:
> 
> process which exceeds CPUTIME limit by setrlimit()
> will not receive signal SIGXCPU and terminate.

Confirmed.

The attached program's output on RELENG_4 (correct):

$ time ./foo
before: cur = 7FFFFFFFFFFFFFFF, max = 7FFFFFFFFFFFFFFF
Setting CPU limit to cur 2, max 5..
after: cur = 2, max = 5
Entering loop..
time: command terminated abnormally
        2.02 real         2.01 user         0.00 sys
Cputime limit exceeded
$

..and on ref5.FreeBSD.org (-current, after waiting a while and hitting ^C):

$ time ./foo
before: cur = 7FFFFFFFFFFFFFFF, max = 7FFFFFFFFFFFFFFF
Setting CPU limit to cur 2, max 5..
after: cur = 2, max = 5
Entering loop..
^CGot signal 2
User: (3, 799606)
System: (0, 7850)
3.800u 0.007s 0:06.08 62.5%     5+178k 0+0io 0pf+0w
$

Something's definitely wrong with -current's setrlimit()..

G'luck,
Peter

-- 
If this sentence didn't exist, somebody would have invented it.

#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>

#include <err.h>
#include <signal.h>
#include <stdio.h>

static volatile int	sig, sigflag;

static void		getlim(const char *, int);
static void		setlim(const char *, int, quad_t, quad_t);
static void		handler(int);

static void
getlim(const char *s, int resource) {
	struct rlimit rlp;

	if (getrlimit(resource, &rlp) < 0)
		err(1, "getrlimit(%s)", s);
	printf("%s: cur = %llX, max = %llX\n", s, rlp.rlim_cur, rlp.rlim_max);
}

static void
setlim(const char *s, int resource, quad_t lcur, quad_t lmax) {
	struct rlimit rlp;

	printf("Setting %s limit to cur %llX, max %llX..\n", s, lcur, lmax);
	rlp.rlim_cur = (quad_t) lcur;
	rlp.rlim_max = (quad_t) lmax;
	if (setrlimit(resource, &rlp) < 0)
		err(1, "setrlimit(%s)", s);
}

static void
handler(int signum __unused) {
	sig = signum;
	sigflag = 1;
}

static void
showrusage(void) {
	struct rusage ru;

	if (getrusage(RUSAGE_SELF, &ru) < 0)
		err(1, "getrusage()");
	printf("User: (%ld, %ld)\nSystem: (%ld, %ld)\n",
	    ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
	    ru.ru_stime.tv_sec, ru.ru_stime.tv_usec);
}

int
main(void) {

	getlim("before", RLIMIT_CPU);
	setlim("CPU", RLIMIT_CPU, 2, 5);
	getlim("after", RLIMIT_CPU);
	printf("Entering loop..\n");
	sig = 0;
	signal(SIGINT, handler);
	while (!sig)
		;
	printf("Got signal %d\n", sig);
	showrusage();
	return (0);
}
Comment 2 Bruce Evans 2001-05-11 10:55:22 UTC
On Fri, 11 May 2001 in@amalea.org wrote:

> >Description:
> 
> process which exceeds CPUTIME limit by setrlimit()
> will not receive signal SIGXCPU and terminate.

This is intentional.  -current is a work in progress:

RCS file: /home/ncvs/src/sys/kern/kern_synch.c,v
Working file: kern_synch.c
head: 1.134
...
----------------------------
revision 1.120
date: 2001/01/20 02:57:59;  author: jhb;  state: Exp;  lines: +6 -1
Temporarily disable the printf() for micruptime() going backwards, the
SIGXCPU signal, and killing of processes that exceed their allowed run
time until they can play nice with sched_lock.  Right now they are just
potentital panics waiting to happen.  The printf() has bitten several
people.
----------------------------

Bruce
Comment 3 ashp freebsd_committer freebsd_triage 2002-01-17 03:30:49 UTC
State Changed
From-To: open->closed

This is not a bug, this is a feature.  The functionality is disabled under 
-CURRENT for a reason, as pointed out by bde.
Comment 4 ashp freebsd_committer freebsd_triage 2002-01-17 20:00:12 UTC
State Changed
From-To: closed->analyzed

Move this to analyzed so that it is taken into account before 5.0 is 
released.
Comment 5 oppermann 2003-12-27 15:51:28 UTC
Bruce,

do you know whether this has been correctly fixed in 5.2RC2 and/or
-CURRENT?

-- 
Andre
Comment 6 Andre Oppermann freebsd_committer freebsd_triage 2003-12-27 15:54:29 UTC
State Changed
From-To: analyzed->feedback

Idle for too long.  Take over for followup. 


Comment 7 Andre Oppermann freebsd_committer freebsd_triage 2003-12-27 15:54:29 UTC
Responsible Changed
From-To: freebsd-bugs->andre

Idle for too long.  Take over for followup.
Comment 8 Bruce Evans 2003-12-27 16:41:31 UTC
On Sat, 27 Dec 2003, Andre Oppermann wrote:

> do you know whether this has been correctly fixed in 5.2RC2 and/or
> -CURRENT?

This is supposed to have been fixed in kern_synch.c revs.1.197-1.198
and associated changes (only in subr_trap.c I think).  Most of the
SIGXCPU handling is now delayed until ast() where it is safe.

Bruce
Comment 9 dwmalone freebsd_committer freebsd_triage 2003-12-28 16:47:54 UTC
State Changed
From-To: feedback->closed

I did a quick test, and this seems to work now.