panic with high signal load

Matthew Dillon dillon at
Thu Mar 26 15:50:38 PDT 2009

:I managed to panic the kernel while doing some testing using signals.
:The application was doing the following:
:fork child
:child sets up signal handler for SIGHUP then loops forever calling
:	pause().
:parent set up signal handler for SIGHUP then parent loops count number
:	of times sending a SIGHUP to the child then calls pause().
:child's SIGHUP handler just sends a SIGHUP to the parent.
:parent's SIGHUP handler calculates the round-trip time for the signal.
:This appears to work fine for count < 1000 or so.  I tried an
:iteration where count = 5000 and panic'ed the kernel.  I was unable to
:get the panic message from the serial console but was able to get the
:following trace from DDB:
:db> trace
:Debugger(c03d444f) at Debugger+0x34
:panic(c03c8398,c040a210,c03c7238,d2684d58,2) at panic+0x9f
:userret(6,0,0,d2684d58,c041f11c) at userret+0x16a
:syscall2(d8c9dd40) at syscall2+0x2d6
:Xint0x80_syscall() at Xint0x80_syscall+0x36
:I can attempt to reproduce this if needed and can also provide the
:source for the application.  I still have the debug kernel but wasn't
:able to glean any useful information from it myself.

    I think I need the program to reproduce it.  I wrote a program based
    on your description, which I include below, but it doesn't seem to
    reproduce the problem.

    In my program instead of having the parent send a SIGHUP from its
    main loop I just have the two signal handlers ping-pong the signal,
    with the child serving the first ball.

					Matthew Dillon 
					<dillon at>

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void sig_child(int sig);
static void sig_parent(int sig);

pid_t Pid_parent;
pid_t Pid_child;

struct timeval Tv1;
struct timeval Tv2;
struct timeval TvDelta;

int64_t Count;

main(int ac, char **av)
    int i;

    Pid_parent = getpid();
    signal(SIGHUP, sig_parent);

    if ((Pid_child = fork()) == 0) {
	Pid_child = getpid();

	signal(SIGHUP, sig_child);
	kill(Pid_parent, SIGHUP);		/* start it going */
	for (;;)

     * NOTE: Count and TvDelta updates can race, so we may occasionally
     * print a bad value.
    for (;;) {
	if (Count % 10000 == 0) {
	    printf("%9lld %6.2fuS\n",
		((double)TvDelta.tv_sec * 1000000.0 +
		(double)TvDelta.tv_usec) / (double)Count

sig_child(int sig)
    kill(Pid_parent, SIGHUP);

sig_parent(int sig)
    int usec;

    Tv1 = Tv2;
    gettimeofday(&Tv2, NULL);
    if (Count > 1) {
	usec = (Tv2.tv_sec - Tv1.tv_sec) * 1000000 +
	       (Tv2.tv_usec - Tv1.tv_usec);

	usec += TvDelta.tv_usec;
	if (usec > 1000000) {
		TvDelta.tv_sec += usec / 1000000;
		usec %= 1000000;
	TvDelta.tv_usec = usec;
    kill(Pid_child, SIGHUP);

More information about the Bugs mailing list