Date: Tue, 28 Oct 2003 13:35:37 -0600 (CST) From: Dan Nelson <dnelson@allantgroup.com> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/58647: itimers aren't cleared on fork() Message-ID: <200310281935.h9SJZbbu041495@dan.emsphone.com> Resent-Message-ID: <200310281940.h9SJeJ2t034734@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 58647 >Category: kern >Synopsis: itimers aren't cleared on fork() >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Oct 28 11:40:18 PST 2003 >Closed-Date: >Last-Modified: >Originator: Dan Nelson >Release: FreeBSD 5.1-CURRENT i386 / FreeBSD 4.8-RELEASE i386 >Organization: The Allant Group, Inc. >Environment: System: FreeBSD dan.emsphone.com 5.1-CURRENT FreeBSD 5.1-CURRENT #295: Mon Oct 27 16:19:10 CST 2003 dan@dan.emsphone.com:/usr/src/sys/i386/compile/DANSMP i386 >Description: POSIX says that all timers are cleared in the child after a fork() (twice in fact): http://www.opengroup.org/onlinepubs/007904975/functions/fork.html [XSI] Interval timers shall be reset in the child process. [TMR] Per-process timers created by the parent shall not be inherited by the child process. FreeBSD 4.x and 5.x, however, only clear ITIMER_REAL. ITIMER_VIRTUAL and ITIMER_PROF both continue to fire in the child process. This could cause problems for any program that uses those timers and also forks (note that userland pthreads uses ITIMER_PROF for its scheduling timer). It definitely causes programs for threaded debuggers, since the profile timer is firing the whole time between the child calling ptrace(PT_TRACE_ME) and exec()'ing the debug target. >How-To-Repeat: Compile the following program and run it. For each received signal, a c or p (child/parent) will be printed, along with a R, V, or P (signal). "p:P", for example means the parent got a SIGPROF. Any "c:" output indicates a bug. #include <unistd.h> #include <sys/time.h> #include <signal.h> char pc = 'p'; /* parent or child */ static void sig_handler(int sig) { /* print what signal we got, and whether we're child or parent, in one atomic write */ char array[4]; array[0] = pc; array[1] = ':'; array[2] = (sig == SIGPROF ? 'P' : sig == SIGVTALRM ? 'V' : sig == SIGALRM ? 'A' : '!'); array[3] = ' '; write(1, &array, 4); } int main(int argc, char *argv[]) { struct itimerval itimer; struct sigaction act; sigemptyset(&act.sa_mask); act.sa_handler = sig_handler; act.sa_flags = SA_RESTART; sigaction(SIGPROF, &act, NULL); sigaction(SIGALRM, &act, NULL); sigaction(SIGVTALRM, &act, NULL); itimer.it_interval.tv_sec = 1; itimer.it_interval.tv_usec = 0; itimer.it_value = itimer.it_interval; setitimer(ITIMER_PROF, &itimer, NULL); setitimer(ITIMER_VIRTUAL, &itimer, NULL); setitimer(ITIMER_REAL, &itimer, NULL); if (fork() == 0) pc = 'c'; for (;;) ; } >Fix: Unknown. It looks like the real timer is stored in a different place from the virtual and profiling timers, which might explain why only the real timer is cleared during fork. >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200310281935.h9SJZbbu041495>