got the alpha 2.0.36 kernel from redhat 5.2/updates for alpha
still got the problem. Attached is a demo ( client/server) program that
demonstrates the loss of the SIGIO interrupt after a few EAGAIN failures. I do
not know why the loss, but for most of the failures there is a I "have no more
buffer space" failure in net/core/sock.c. BUT since SIGIO's were gen'd a few
times under the same "lack" of space scenario, i have no hard facts to point a
firm belief that the buffer failure is the absolute cause.
gat
tomm i will fire up the 386, and see how that fairs.
Alan Cox wrote:
> updates. I'm not interested in 2.0.33 network problems unless they are also
> duplicatable on .35/36.
>
> Alan
/* * server.c
* cc -g -o server server.c
* To demonstrate unexpected SIGIO loss
* [EMAIL PROTECTED]
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
int fd, work_fd;
main()
{
char *p1, *p2;
struct iovec iovec[2];
int i;
int j = 0;
open_socket();
p2 = malloc( 10*1024 );
iovec[0].iov_len = 10*1024;
iovec[0].iov_base = p2;
while( i > 0 ) {
i = readv(work_fd, &iovec, 1);
printf("%d\n",j++);
}
unlink("X0");
}
open_socket()
{
struct sockaddr_un sockname, sockname2;
int i;
int len;
fd = socket(1,1,0);
if ( fd < 0 ) {
printf("Socket error %d\n", errno);
exit();
}
unlink("X0");
sockname.sun_family = AF_UNIX;
len = sprintf(sockname.sun_path,"X0");
len += sizeof(sockname.sun_family);
i = bind( fd, &sockname, len);
if ( i<0 ) {
printf("Cannot connect to &s, errno=%d\n",
sockname.sun_path, errno);
exit();
}
i = listen( fd, 2 );
i = 50;
work_fd = accept( fd, &sockname2, &i);
#if 0
i = fcntl( fd, F_GETFL,0);
fcntl( fd, F_SETFL, O_NONBLOCK | i);
fcntl( fd, F_SETOWN, getpid());
#endif
}
/******************** end of server.c *****************************/
/*
* client.c
* cc -g -o client client.c
* To demonstrate SIGIO loss.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
int fd;
void io_done(int);
void timedout(int);
int myv( int fd, struct iovec *a, size_t b);
long gettime();
#define A_LONG_TIME (30*1000) /* 30 seconds */
enum timeouts { GOT_IO=34,GOT_TIME };
struct {
long begin_time;
long end_time;
enum timeouts flag;
} t;
main()
{
char *p1, *p2;
int loops=0;
struct iovec iovec[2];
signal( SIGALRM, timedout);
signal( SIGIO, io_done);
open_socket();
p1 = malloc(24);
p2 = malloc( 262123 );
while(1){
iovec[0].iov_len = 24;
iovec[0].iov_base = p1;
iovec[1].iov_len = 200*1024-24;
iovec[1].iov_base = p2;
myv( fd, (struct iovec *)&iovec, 2);
printf("Loops = %d\n",loops++);
nod_off(500, "Delay"); /* 500ms */
}
}
myv( int fd,struct iovec * vec , size_t c)
{
int wrote, left;
struct iovec *iov;
iov = vec;
while (c > 0 ) {
t.begin_time = 0;
t.end_time = 0;
wrote = writev( fd, iov, c );
if ( wrote < 0 ) {
if ( errno == EAGAIN ) {
nod_off( A_LONG_TIME ,"EAGAIN");
continue;
}
printf("Unexpected writev error %d\n", errno);
}
for ( ; c; iov++,c--) {
left = wrote - iov->iov_len;
if ( left >= 0 ) {
wrote -= iov->iov_len;
continue;
}
iov->iov_len -= wrote;
iov->iov_base += wrote;
break;
}
}
}
nod_off( int time , char *m)
{
struct itimerval value;
int i;
int status;
value.it_interval.tv_sec = 0;
value.it_interval.tv_usec = 0;
value.it_value.tv_sec = time/1000;
value.it_value.tv_usec = (time%1000)*1000;
setitimer( ITIMER_REAL, &value, 0 );
if ( t.begin_time || t.end_time ) {
printf(" Signal Happened after writev. (b=%lx,e=%lx)\n",
t.begin_time, t.end_time);
}
t.begin_time = gettime();
t.end_time = 0;
i = pause(); /* ZZZZZZZZZZZZZzzzzzzzzzzzzzzzzz........ */
if (i >= 0 ) /* ??? */
;
if ( m[0] != 'D') {
printf("Woke up(%d): time.b=%lx,time.e=%lx,Reason=%s\n",
errno, t.begin_time, t.end_time,
(t.flag == GOT_IO)?"SIGIO":"TimedOut");
}
}
open_socket()
{
struct sockaddr_un sockname;
int i;
int len;
fd = socket(PF_UNIX,SOCK_STREAM,0);
if ( fd < 0 ) {
printf("Socket error %d\n", errno);
exit(1);
}
sockname.sun_family = AF_UNIX;
len = sprintf(sockname.sun_path,"X0");
len += sizeof(sockname.sun_family);
i = connect( fd, &sockname, len);
if ( i<0 ) {
printf("Cannot connect to %s, errno=%d\n",
sockname.sun_path, errno);
exit(2);
}
i = fcntl( fd, F_GETFL,0);
if ( i < 0 ) exit(3);
i = fcntl( fd, F_SETFL, O_NONBLOCK | O_ASYNC | i);
if ( i < 0 ) exit(4);
i = fcntl( fd, F_SETOWN, getpid());
if ( i < 0 ) exit(4);
i = fcntl( fd, F_GETFL,0);
}
void
timedout(int sig )
{
t.end_time = gettime();
t.flag = GOT_TIME;
signal(sig, timedout);
}
void
io_done(int sig )
{
t.end_time = gettime();
t.flag = GOT_IO;
signal( sig, io_done);
}
long
gettime()
{
struct timeval tv;
gettimeofday( &tv, 0);
return (tv.tv_sec*1000L + tv.tv_usec/1000L);
}
/****************** end of client.c *********************************/