Have sigpoll and sigio band field match glibc for n64
PATCH 1/1 Have sigpoll and sigio band field match glibc for n64.
In reply to Peter WatkinsFrom: Peter Watkins <[email protected]>
--- include/asm-mips/siginfo.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
include/asm-mips/siginfo.h +2 -0
@@ -32,6 +32,8 @@ #ifdef CONFIG_64BIT#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))#endif +#define __ARCH_SI_BAND_T int +#include <asm-generic/siginfo.h> typedef struct siginfo {
Signature · 1 line
1.4.2.4
PATCH 1/1 Have sigpoll and sigio band field match glibc for n64
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;
}Quoted 2 lines · Peter Watkins
The siginfo field
si_fdis incorrect on n64 because the band field does not match glibc.
Susv3 says:
[...]
The <signal.h> header shall define the siginfo_t type as a structure that includes at least the following members:
[...]
long si_band Band event for SIGPOLL.
[...]
So the kernel is right, glibc is wrong I'd say ...
Ralf
Quoted 11 lines · Ralf Baechle
Quoted 2 lines · Peter Watkins
The siginfo field
si_fdis incorrect on n64 because the band field does not match glibc.Susv3 says:
[...]
The <signal.h> header shall define thesiginfo_ttype as a structure that includes at least the following members:
Quoted 5 lines
[...]
longsi_bandBand event for SIGPOLL.
[...]So the kernel is right, glibc is wrong I'd say ...
This will break the ABI only for uses of si_band and si_fd, and only on n64. Anyone see a reason why I shouldn't change glibc?
Ralf, as I mentioned on IRC, I've got bigger worries about siginfo. Shouldn't n32 be using the same siginfo as o32? It's got pointers in it.
Signature · 2 lines
Daniel Jacobowitz CodeSourcery
Quoted 5 lines · Daniel Jacobowitz
This will break the ABI only for uses of
si_bandandsi_fd, and only on n64. Anyone see a reason why I shouldn't change glibc?Ralf, as I mentioned on IRC, I've got bigger worries about siginfo. Shouldn't n32 be using the same siginfo as o32? It's got pointers in it.
Yes, you're right. Will you cook up a patch?
Ralf
Quoted 9 lines · Ralf Baechle
Quoted 5 lines · Daniel Jacobowitz
This will break the ABI only for uses of
si_bandandsi_fd, and only on n64. Anyone see a reason why I shouldn't change glibc?Ralf, as I mentioned on IRC, I've got bigger worries about siginfo. Shouldn't n32 be using the same siginfo as o32? It's got pointers in it.
Yes, you're right. Will you cook up a patch?
I won't have time any time soon - my MIPS board isn't hooked up. If no one has by the time I get around to it next, though, I'll try.
Signature · 2 lines
Daniel Jacobowitz CodeSourcery
Quoted 2 lines · Daniel Jacobowitz
I won't have time any time soon - my MIPS board isn't hooked up. If no one has by the time I get around to it next, though, I'll try.
Oh well, it's reasonably straight forward, so I guess I can try to fix that but I don't have an N32 setup for testing ...
Ralf