Subject: Re: possible bug in NetBSD asynchronous I/O
To: None <tech-kern@netbsd.org>
From: Christos Zoulas <christos@zoulas.com>
List: tech-kern
Date: 04/28/2001 15:20:13
In article <1eskqxj.oy2s6iqcuvccM%p99dreyf@criens.u-psud.fr>,
Emmanuel Dreyfus <p99dreyf@criens.u-psud.fr> wrote:

FASYNC == O_ASYNC which is documented to send SIGIO. That is
what asynchronous/io is.

christos

>Hello everybody
>
>With the help of Kevin B. Hendricks, I'm tracking down a bug in Linux
>emulation that hangs the JDK on the PowerPC on some rare operations (so
>far, this bug pops up when building Ant, and also probably when running
>Tomcat)
>
>Here is the problem: We use async I/O to send data from one process to
>another through a pipe. It seems that when the receiving process reads
>some data from the pipe, the sending process gets a unexpected SIGIO.
>This confuses the JDK.
>
>There is a test program that reveals the problem at the end of this
>message. I wonder if this couldn't be more global than just an emulation
>problem. I ran it as a native binary on Linux, NetBSD, FreeBSD, OpenBSD,
>and Solaris, and NetBSD is the only OS out of there with this behavior.
>All other OSes pass the test successfully.
>
>I don't know what is the standard behavior here, or even if the behavior
>is standardized, but it seems we are not behaving like other UNIXes
>here. Could we have a standard conformance problem? I mean is it a bug
>or a feature? Should this be fixed only for Linux binaries (because this
>is a bug for Linux binaries), or should it be fixed at a lower level,
>for all emulation packages?
>
>/* sigio.c -- tests for a possible NetBSD async I/O bug */
>#include <signal.h>
>#include <string.h>
>#include <unistd.h>
>#include <stdlib.h>
>#include <stdio.h>
>#include <sys/types.h>
>#ifdef linux
>#include <wait.h>
>#include <error.h>
>#endif
>#ifdef __NetBSD__
>#include <sys/wait.h>
>#endif
>#include <fcntl.h>
>#include <sys/fcntl.h>
>#include <errno.h>
>
>static void 
>io_sighandler(int sig)
>{
>
>  fprintf(stderr,"##### %d: We got sigio .. in handler\nTEST FAILED\n",
>getpid());
>  fflush(stderr);
>  exit (-1);
>}
>
>
>int 
>main(int argc, char** argv)
>{
>    struct sigaction chld;
>    struct sigaction aio;
>    pid_t pid;
>    int   status;
>    int fdsync[2];
>    int err;
>    char c;
>    sigset_t set;
>
>    sigemptyset(&set);
>    sigaddset(&set,SIGIO);
>
>    fdsync[0] = fdsync[1] = -1;
>    if (pipe(fdsync) < 0) { /* fd for synchronization */
>      fprintf(stderr, "Error: bad pipe call\n");
>      exit(1);
>    }
>
>    aio.sa_flags = SA_RESTART;
>    aio.sa_handler = io_sighandler;
>    sigemptyset(&aio.sa_mask);
>    if (sigaction(SIGIO, &aio, 0) == -1) {
>        fprintf(stdout,"Error: Bad return value from sigaction call\n");
>        exit(1);
>    }
>
>    /* now set the pipe write end to be non-blocking async */
>    fcntl(fdsync[1],F_SETFL, O_NONBLOCK | FASYNC);
>    fcntl(fdsync[1],F_SETOWN, getpid());
>
>    fprintf(stdout,"going to fork\n");
>    fflush(stdout);
>    if ((pid = fork()) == 0) {
>        /* Child process XXX */
>
>        /* wait until parent is ready before preceding */
>
>        printf("doing err = read(fdsync[0], &c, 1);\n");
>        err = read(fdsync[0], &c, 1);
>
>        exit (0);
>    } else {
>       /* the parent */
>
>       fprintf(stdout,"parent: pid=%d\n", getpid());
>       fprintf(stdout,"going to wait\n");
>       fflush(stdout);
>
>       /* tell child we are ready to go */
>       err = write(fdsync[1], "AAAA", 4);
>       if (err < 0) {
>          fprintf(stderr,"got err=%d\n", err);
>          fflush(stderr);
>       }
>
>            /* pause(); */
>       sleep (10);
>       fprintf(stdout,"reaped pid %d\nTEST SUCCESSFUL\n",pid);
>       fflush(stdout);
>
>       exit(0);
>       }
>}
>
>
>-- 
>Emmanuel Dreyfus
>p99dreyf@criens.u-psud.fr