Mail Archives: cygwin/1998/04/28/04:59:07
Hi,
It looks like another cygwin bug. The following is a test program which
behaves incorrectly in cygwin. I ran it in cygwin beta 19.1 as:
remote% nc -l -p 3333
cygwin$ ./testcase
The program connects from cyginw to remote, then it sequentially tries
to connect to a few ports (notice how slow the connection attempts are;
winsock seems to be very slow at reacting to RST's after SYN's). After
some time a signal handler is invoked which warps the program back
out to main. At this point a write to the original connected socket
will fail with EINPROGRESS (sometimes. it appears this is a race).
This should not happen! My best guess is that the signal handler warped
out of the cygwin connect() function and cygwin was left in a weird state
in which future operations fail. EINPROGRESS is not even a valid
error response for write().
The error can also be observed when sigsetjmp/siglongjmp is not used
but socket operations are performed directly from the signal handler.
fix: not sure. perhaps some parts of the code need to be protected
from interruption by signals.
Tim N.
---- test case ----
/*
* Connect to REMOTE port 3333 (I use nc -l -p 3333 on remote host for testing)
* then attempt to connect to ports on REMOTE until timeout
* after TIMEOUT, try to write to REMOTE.
*
* Error: write() to REMOTE at end (after jumping from signal handler)
* results in error with errno = 119 sometimes (EINPROGRESS). This should
* not happen. The same thing is observed if the write is done directly
* from the signal handler.
*
* Synopsis: Jumping out of some calls leaves the system in a weird state?
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#define REMOTE "10.200.200.3"
static sigjmp_buf jmpbuf;
static void
jumper(int sig)
{
siglongjmp(jmpbuf, 1);
}
int
connect_sock(int addr, int port)
{
struct sockaddr_in ad;
int s;
s = socket(AF_INET, SOCK_STREAM, 0);
if(s == -1) {
perror("socket");
exit(1);
}
memset(&ad, 0, sizeof ad);
ad.sin_family = AF_INET;
ad.sin_addr.s_addr = addr;
ad.sin_port = htons(port);
if(connect(s, (struct sockaddr *)&ad, sizeof ad) == -1) {
close(s);
return -1;
}
return s;
}
int
set_nonblock(int fd, int flag)
{
return ioctl(fd, FIONBIO, &flag);
}
int
main()
{
int s, sx, port, addr, res;
char c;
signal(SIGALRM, jumper);
sx = connect_sock(inet_addr("10.200.200.3"), 3333);
printf("sx is %d\n", sx);
addr = inet_addr("10.200.200.3");
alarm(5);
if(sigsetjmp(jmpbuf, 1) == 0) {
for(port = 1; port < 40; port++) {
printf("try %d\n", port);
s = connect_sock(addr, port);
if(s == -1)
continue;
printf("%d connected\n", port);
set_nonblock(s, 1);
write(s, "test", 4);
read(s, &c, 1);
close(s);
}
} else {
printf("timeout\n");
}
res = write(sx, "test", 4);
if(res == -1)
printf("error: %s\n", strerror(errno));
else
printf("res %d\n", res);
return 0;
}
-
For help on using this list (especially unsubscribing), send a message to
"gnu-win32-request AT cygnus DOT com" with one line of text: "help".
- Raw text -