Subject: Re: pipes from FreeBSD and the NetBSD async I/O bug
To: Ben Harris <bjh21@netbsd.org>
From: Emmanuel Dreyfus <p99dreyf@criens.u-psud.fr>
List: tech-kern
Date: 05/01/2001 00:54:06
> Since the behaviour of the old pipes will presumably also apply to
> Unix-domain sockets, they'll need fixing (or proving correct) anyway, won=
't
> they?

I've made a test program for sockets, it's at the end of this post.=20
Here the results are quite different across OSes:

Do send SIGIO on any read when the write end is set as async (the test
says it failed): NetBSD-current, OpenBSD-2.6, FreeBSD-3.4, Digital
UNIX-4.0,=20
Do no send SIGIO (the program says it succeds): Solaris-2.6, Linux-2.2.x
It would be interesting to test on other OSes.

So here I don't know what is the good behavior. If we assume it is the
Linux and Solaris way and we fix it, then we might break FreeBSD
emulation, as FreeBSD implements it the other way. But if we just keep
it the way it is now, we keep Linux and Solaris emulation broken.

For pipes, it was easy: everyone do it one way and we are alone doing it
the other way. For UNIX sockets, it's trickier. I'd really like to know
what the standards says about this. Is there a good behavior, or is it
simply left unspecified?

We have to think about a fix to this that would not break FreeBSD
emulation. Maybe having a flag in the socket to request for one behavior
or the other, and this flag would be set according to the emulation and
the kind of sockets (pipes are to be treated differently than UNIX
sockets for FreeBSD emulation). One open question is where to fold that
flag in struct socket? (which field?)

I think this would mean adding a boolean to sowakeup() to enable or
disable the SIGIO. And the sowwakeup in usrreq (case PRU_RCVD) could
disable the SIGIO depending on the socket flag. I can try implementing
this if onbody has something against it.

And the last question is what behavor should be used for NetBSD native
binaries? I beleive the answer to that question is to keep to the
standard behavior, but I don't know what the standard says. Someone has
POSIX specs on his desktop?

Another note: Digital UNIX 4.0 fails on the pipe test. I've found
another OS that does pipe async I/O the same way we do it.


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>

void io_sighandler (int sig) {
  printf ("pid=3D%d got sigio\n", getpid ());
  printf ("TEST FAILED\n");
  exit (-1);
}

int main(int argc, char** argv) {
    struct sigaction aio;
    int fdsync[2];
    int err;
    char c;
    sigset_t set;

    sigemptyset(&set);
    sigaddset(&set,SIGIO);

    aio.sa_flags =3D SA_RESTART;
    aio.sa_handler =3D io_sighandler;
    sigemptyset(&aio.sa_mask);
    if (sigaction(SIGIO, &aio, 0) =3D=3D -1) {
        printf("Error: Bad return value from sigaction call\n");
        exit(1);
    }

    if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fdsync) < 0) { /* fd
for synchronization */
      printf("Error: bad socketpair 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());

    err =3D write(fdsync[1], "AAAA", 4);
    if (err < 0) {
       printf("write() got err=3D%d\n", err);
    }
    printf ("written %d bytes\n", err);

    sleep (1);

    do=20
       err =3D read(fdsync[0], &c, 1);
    while (!err);
    printf ("readen %d bytes\n", err);

    printf("TEST SUCCESSFUL\n");
    exit(0);
}
--=20
Emmanuel Dreyfus. =20
Vous avez deplac=E9 la souris.=20
Windows NT doit maintenant redemarrer pour valider les modifications.
p99dreyf@criens.u-psud.fr