Hello, The siginfo field si_fd is incorrect on n64 because the band field does not match glibc. The patch is in the next mail. Tested on Malta and Sicortex. Below is how to reproduce the problem. run ./sigio on mips64 testmachine on another machine, telnet testmachine 8888 Correct output: gcc -o sigio sigio.c -mabi=n32 ./sigio fd 3 sock 4 sigio : fd 1065 sigio : fd 4 sigio : fd 4 sigio : fd 4 sigio : fd 4 sigio : fd 4 sigio : fd 4 ... Incorrect output: gcc -o sigio sigio.c -mabi=64 ./sigio fd 3 sock 4 sigio : fd 1065 sigio : fd 0 sigio : fd 0 sigio : fd 0 sigio : fd 0 sigio : fd 0 Test program (from Andrew Gierth) #define _GNU_SOURCE 1 #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/time.h> #include <netinet/in.h> #include <stdio.h> #include <stdarg.h> #include <signal.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #define TCP_PORT 8888 /* This example uses SIGIO and SIGURG on a TCP socket for convenience. */ /* In practice, SIGIO is almost useless on stream sockets, because it */ /* gets generated by far too many different events. */ /* To test, just telnet to port 8888. Use telnet's 'synch' command to */ /* generate OOB data for SIGURG. */ /* The program simply echos data in hex, bracketing all 'urgent' data */ /* in []. */ /* I say again: USE SIGIO ON STREAM SOCKETS ONLY AS A LAST RESORT. */ /* handle cruft */ #if EWOULDBLOCK == EAGAIN # define IS_WOULDBLOCK(err) ((err)==EAGAIN) #else # define IS_WOULDBLOCK(err) (((err)==EAGAIN)||((err)==EWOULDBLOCK)) #endif /* useful functions */ void errexit(const char *msg) { perror(msg); exit(1); } /* this is done this way in an attempt to be safe in a signal handler. */ void complain(const char *msg,...) { va_list va; char buf[1024]; va_start(va,msg); vsprintf(buf, msg, va); va_end(va); write(STDERR_FILENO, buf, strlen(buf)); } /* might need fcntl(F_SETFL), or ioctl(FIONBIO) */ /* Posix.1g says fcntl */ /* NEVER, EVER USE O_NDELAY HERE */ #ifdef O_NONBLOCK int set_nonblock(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) return -1; return fcntl(fd, F_SETFL, flags | O_NONBLOCK); } #else int set_nonblock(int fd) { int yes = 1; return ioctl(fd, FIONBIO, &yes); } #endif /* might need fcntl(F_SETOWN), or ioctl(FIOSETOWN), or ioctl(SIOCSPGRP) */ /* Posix.1g says fcntl */ #ifdef F_SETOWN int set_owner(int fd) { return fcntl(fd, F_SETOWN, getpid()); } #else int set_owner(int fd) { pid_t pid = getpid(); return ioctl(fd, FIOSETOWN, &pid); } #endif /* might need fcntl(F_SETFL), or ioctl(FIOASYNC) */ /* Posix.1g says fcntl */ /* DONT use I_SETSIG unless portability isn't an issue - remember, */ /* SOCKETS ARE NOT STREAMS! */ #ifdef O_ASYNC int set_async(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) return -1; return fcntl(fd, F_SETFL, flags | O_ASYNC); } #else int set_async(int fd) { int yes = 1; return ioctl(fd, FIOASYNC, &yes); } #endif int sockatmark(int sock) { int flag = 0; if (ioctl(sock, SIOCATMARK, &flag) < 0) return -1; return (flag != 0) ? 1 : 0; } /* Ought to be able to do this with SIOCATMARK, but on my FreeBSD system */ /* it wasn't behaving in any sort of consistent fashion. */ int urgent_pending(int sock) { struct timeval tv; fd_set fds; FD_ZERO(&fds); FD_SET(sock,&fds); tv.tv_sec = 0; tv.tv_usec = 0; return select(sock+1,NULL,NULL,&fds,&tv); } /*-------------------------------------------------------------------------*/ int sock; sigset_t sigio_set; sigset_t sigurg_set; sigset_t empty_set; volatile sig_atomic_t urgmode = 0; volatile sig_atomic_t sigiocount = 0; volatile sig_atomic_t sigurgcount = 0; void sigio_handler(int sig, struct siginfo *info, void *data) { char inbuf[64]; char outbuf[4]; int i,rc,flag; sigset_t sigs; sigiocount++; complain("sigio : fd %d \n", info->si_fd); for (;;) { rc = read(sock, inbuf, sizeof(inbuf)); if (rc < 0 && IS_WOULDBLOCK(errno)) return; if (rc < 0) { complain("error on read: %d (%s)\n", errno, strerror(errno)); _exit(1); } if (rc == 0) { complain("Done.\n"); complain("Total SIGIOs : %ld\n", (long) sigiocount); complain("Total SIGURGs: %ld\n", (long) sigurgcount); _exit(0); } for (i = 0; i < rc; i++) { outbuf[0] = ' '; outbuf[1] = "0123456789ABCDEF"[(inbuf[i] >> 4) & 0x0F]; outbuf[2] = "0123456789ABCDEF"[inbuf[i] & 0x0F]; write(sock, outbuf, 3); } sigprocmask(SIG_BLOCK, &sigurg_set, &sigs); if (urgmode && !urgent_pending(sock)) { write(sock, "]", 1); urgmode = 0; } sigprocmask(SIG_SETMASK, &sigs, NULL); } } void sigurg_handler(int sig) { sigurgcount++; urgmode = 1; write(sock, " [", 2); } main() { struct sigaction sa; struct sockaddr_in addr; int addrlen = sizeof(addr); int fd = socket(AF_INET, SOCK_STREAM, 0); int yes = 1; if (fd < 0) errexit("socket"); sigemptyset(&empty_set); sigemptyset(&sigio_set); sigaddset(&sigio_set,SIGIO); sigemptyset(&sigurg_set); sigaddset(&sigurg_set,SIGURG); if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) errexit("setsockopt"); /* set this in the listen socket; it will be inherited. */ if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &yes, sizeof(int)) < 0) errexit("setsockopt"); addr.sin_family = AF_INET; addr.sin_port = htons(TCP_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (bind(fd, (struct sockaddr *) &addr, addrlen) < 0) errexit("bind"); if (listen(fd,5) < 0) errexit("listen"); sock = accept(fd, (struct sockaddr *) &addr, &addrlen); if (sock < 0) errexit("accept"); printf("fd %d sock %d\n", fd, sock); close(fd); /* block SIGIO and SIGURG while we set everything up. */ sigprocmask(SIG_BLOCK, &sigio_set, NULL); sigprocmask(SIG_BLOCK, &sigurg_set, NULL); if (set_nonblock(sock) < 0) errexit("set_nonblock"); if (set_owner(sock) < 0) errexit("set_owner"); if (set_async(sock) < 0) errexit("set_async"); sa.sa_handler = sigio_handler; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sigaction(SIGIO, &sa, NULL); sa.sa_handler = sigurg_handler; sa.sa_flags = 0; sa.sa_mask = sigio_set; sigaction(SIGURG, &sa, NULL); int ret; ret = fcntl(sock, F_SETSIG, SIGIO); if (ret == -1) { printf("cannot setsig: %s\n", strerror(errno)); errexit("setsig"); } /* data may have arrived while we were setting up, so generate */ /* SIGIO now. */ raise(SIGIO); /* unblock everything, then pause. */ sigprocmask(SIG_SETMASK, &empty_set, NULL); for(;;) pause(); /*NOTREACHED*/ return 0; }