In article <31E252A9.4...@hydro.on.ca> Rob Allan
<rob.e.al...@hydro.on.ca> writes:
> When I do an ftp to a remote sight via 14.4 baud modems on a netblazer,
> the mouse/windowing response on my ultra really slows down. It feels
> like the cpu is pinned. But the perfmeter shows everything at a low
> level; cpu, interupts, disk etc. This doesn't happen during local or
> internet ftp's.
> This only happens on 2.5 under CDE 1.0.1. Under 4.1.3 we never saw this.
> I've tested it on a sparc 5 as well and it still happens.
This is in fact triggered by TCP connections from a 2.5 machine that
are blocked while sending data. It can happen on local file transfers,
too.
Below is a test program that reproduces the bug. Compile it with
gcc -o tcp tcp.c -lsocket -lnsl. Then start the receiving side with
``tcp'' in one window and the sending side with ``tcp -s localhost''
in another. After each received Mbyte, the receiving process sleeps for
5 seconds. Note the jerky mouse cursor while the connection is blocked.
Unfortunatelly, there doesn't seem to exist a workaround or a patch
for this problem. The [Preliminary] ``Solaris TCP Retransmission
patches'' don't seem to help.
------ tcp.c -----------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
extern int optind;
extern char *optarg;
void
usage()
{
fprintf(stderr, "usage: [-d sec] [-p port] [-s host]\n");
fprintf(stderr, "\t-d: delay in seconds after receiving 1M of data\n");
fprintf(stderr, "\t-p: port\n");
fprintf(stderr, "\t-s: send data to host, without -s receive data\n");
exit(1);
}
int
main(argc, argv)
char **argv;
{
int c, i, n;
int total, kb, last_kb_printed;
int delay_kb;
char *host = "localhost";
int port = 4711;
int delay = 5;
enum { SEND, RECV } mode = RECV;
int s;
struct hostent *he;
struct sockaddr_in sin;
int sin_len;
char buf[8192];
while ((c = getopt(argc, argv, "d:p:s:")) != -1) {
switch (c) {
case 'p':
port = atoi(optarg);
break;
case 's':
host = optarg;
mode = SEND;
break;
case 'd':
delay = atoi(optarg);
break;
default:
usage();
}
}
if (argv[optind]) usage();
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("socket AF_INET");
exit(1);
}
if (mode == SEND) {
he = gethostbyname(host);
if (he == NULL) {
fprintf(stderr, "host %s unknown\n", host);
exit(1);
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
memcpy(&sin.sin_addr, he->h_addr, he->h_length);
if (connect(s, (void *)&sin, sizeof(sin)) < 0) {
perror("connect");
exit(1);
}
for (total = last_kb_printed = 0;;) {
n = write(s, buf, sizeof(buf));
if (n < 0) {
perror("write");
exit(1);
}
total += n;
kb = total >> 10;
if (kb != last_kb_printed) {
printf("\r%d", kb);
fflush(stdout);
last_kb_printed = kb;
}
}
} else {
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (void *)&sin, sizeof(sin))) {
perror("bind port");
exit(1);
}
if (listen(s, 5)) {
perror("listen");
exit(1);
}
printf("receive data, waiting for connection\n");
if ((s = accept(s, (void *)&sin, &sin_len)) < 0) {
perror("accept");
exit(1);
}
delay_kb = 1000;
for (total = last_kb_printed = 0;;) {
n = read(s, buf, sizeof(buf));
if (n < 0) {
perror("read");
exit(1);
}
if (n == 0) break;
total += n;
kb = total >> 10;
if (kb != last_kb_printed) {
printf("\r%d", kb);
fflush(stdout);
last_kb_printed = kb;
}
if (kb > delay_kb) {
sleep(delay);
delay_kb += 1000;
}
}
}
}
--
Juergen Keil j...@tools.de ...!{uunet,mcsun}!unido!tools!jk