Subject: port-i386/1832: FPE bug in i386 1.1
To: None <gnats-bugs@gnats.netbsd.org>
From: Neil J. McRae <neil@demon.net>
List: netbsd-bugs
Date: 12/12/1995 12:37:39
>Number:         1832
>Category:       port-i386
>Synopsis:       NetBSD 1.1 has severe FPE bugs.
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Dec 12 07:50:00 1995
>Last-Modified:
>Originator:     Neil J. McRae
>Organization:
Neil J. McRae.                                            Demon Internet
neil@demon.net
 NetBSD: Free the daemon in your <a href="http://www.NetBSD.ORG/">computer!</a>
>Release:        NetBSD 1.1
>Environment:
System: NetBSD NetBSD.noc.demon.net 1.1 NetBSD 1.1 (NETBSD) #4: Fri Dec 1 16:32:30 GMT 1995 neil@NetBSD.corp.demon.net:/usr/src/sys/arch/sparc/compile/NETBSD sparc


>Description:
The FPE code in NetBSD 1.1 has several bugs that cause programs that use
it to coreth dumpeth.
>How-To-Repeat:

/*
 * attempt to provoke the FPE bug in NetBSD 1.1 
 * We for lots of little children which all do FP work.  The NPX doesn't
 * seem to be correctly reset for some of the children so we blow up with
 * what seems to be FP stack overflow ?
 *
 * Compile with -DFLOAT to enable the test.

#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <sys/wait.h>

/*
 * gcc 2.4.5 doesn't seem to understand sig_atomic_t properly.
 * On a machine with FPU disabled, this will cause the program to hang
 * after a while.  This does not invalidate the test.
 */
sig_atomic_t count = 0;
#define MAX 5

void handler()
{
  int pid, status;
  while ((pid = wait(&status)) > 0) {
    count--;
    if (WIFSIGNALED(status)) {
      printf("Child died on signal %d\n", WTERMSIG(status));
      exit(1);
    }
  }
  /* if (pid < 0)
	perror("wait"); */
}

void xhandler()
{
printf("alarm clock, count = %d\n", count);
alarm(5); handler();
}

int do_one()
{
  int pid;
  if ((pid = fork()) > 0) {
    /* parent */
    count++;
    printf("parent: %d children\n", count);
  }
  else {
    int i;
#ifdef FLOAT
    /* child */ 
    float answer;
      
    answer = 0.5 * 23;
    printf("child %d: answer = %f\n", getpid(), answer);
#endif
    exit(0);
  }
  return 0;
}

int main (int argc, char *argv[])
{

  struct sigaction action;

  action.sa_handler = handler;
  action.sa_mask = 0;
  action.sa_flags = SA_NOCLDSTOP;

  sigaction(SIGCHLD, &action, 0);

  action.sa_handler = xhandler;
  sigaction(SIGALRM, &action, 0);

  alarm(5);
  while (1) {
    /* printf("again\n"); */
    while (count < MAX)
      do_one();
    pause();
  }
}

>Fix:
Workaround: Disable the FPU (ewww) but this makes X almost useless!

*** /usr/src/sys/arch/i386/isa/npx.c    Sat Oct 14 02:58:53 1995
--- /sys/arch/i386/isa/npx.c    Fri Nov 24 11:13:06 1995
***************
*** 221,226 ****
--- 221,230 ----
                                npx_type = NPX_BROKEN;
                                ia->ia_irq = IRQUNK;
                        }
+ #ifdef IGNOREFPU
+                       npx_type = NPX_BROKEN;
+                       ia->ia_irq = IRQUNK;
+ #endif
                        return 1;
                }
        }

>Audit-Trail:
>Unformatted: