Bug (??) in BSD real itimer -- doesn' propogate across forks.

David Hitz hitz at mips.COM
Fri Jan 29 14:23:28 AEST 1988


I've found a bug in the BSD4.3 setitimer() system call, and I thought
I'd run it by the wizards.

Problem is, both the virtual timer and the profiling timer propagate
across fork system calls, but the real timer does not.  This is true on
both a VAX and a MIPS box.  (I've included a simple test case at the
end of this message.)

I looked at the code to see if this looked accidental or on purpose,
Since the real timer needs to be implemented differently from the other
two, the results were ambiguous.  

Real timer info must always be present so it goes into proc instead of
user, and it would be too inefficient to trigger it with an explicit
check in hardclock() as with the other two, so it's done with timeout()
instead.

But in newproc() kern_fork.c:

	timerclear(&rpp->p_realtimer.it_value);

This looks on purpose, but it may have been an incorrect fix added to
make getitimer() reflect that fact that the real timer wasn't getting
propogated.  Coping the values from the parent isn't enough to restart
the real timer, you also have to put:

	timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value));

somewhere in newproc().

So can I fix this?  It isn't documented in fork(), and I can't think of
any good reason for the real timer to be special.  On the other hand,
who knows what code will die when it suddenly has to deal with an extra
signal.

Yo?
------- Short test case --------------------------------------------------------
/*
 *  Prints messages on receipt of each of the three timer signals,
 *  both from parent and child.  (Parent on left, child on right.)
 */

#include <sys/param.h>
#include <sys/signal.h>
#include <sys/time.h>

int child, sigalrm(), sigvtalrm(), sigprof();

main()
{
	struct itimerval it;

	it.it_interval.tv_sec = 0;
	it.it_interval.tv_usec = 500000;
	it.it_value.tv_sec = 0;
	it.it_value.tv_usec = 1;

	signal(SIGALRM, sigalrm); 
	signal(SIGVTALRM, sigvtalrm);
	signal(SIGPROF, sigprof);

	setitimer(0, &it, 0); 
	setitimer(1, &it, 0);
	setitimer(2, &it, 0);

	child = fork();
	if (child == -1) {
		perror("fork");
		exit(1);
	}
	child = !child;		/* True if child */

	while (1);
}

sigalrm() {
	static int alrm;
	printf("\t%sR%d\n", child?"\t\t\t\t\t":"", alrm);
	++alrm;
}

sigprof() {
	static int prof;
	printf("\t\t%sP%d\n", child?"\t\t\t\t\t":"", prof);
	++prof;
}

sigvtalrm() {
	static int vtalrm;
	printf("\t\t\t%sV%d\n", child?"\t\t\t\t\t":"", vtalrm);
	++vtalrm;
}
--------------------------------------------------------------------------------
-- 
Dave Hitz
UUCP: {decvax,ucbvax,ihnp4}!decwrl!mips!hitz 	DDD: hitz at 408-991-0345



More information about the Comp.unix.wizards mailing list