|
|
Joe Orton wrote:
Can you describe precisely what problems were seen, and when the
ENOTCONN was triggered? It's important to be able to distinguish
between a *closed* and a *reset* socket. The above description could
mean anything really. Have you run "make check" on this platform?
My PC DOS program uses Neon 0.24.7 and Watt-32 to connect to Apache 2.
If I use persistent connections, and the timeout expires on the server
between requests, ne_request_dispatch() returns an error for the
following request relating to the ENOTCONN return code. If I hack
Watt-32 to use EPIPE, Neon works perfectly for me.
Unfortunately, "make check" doesn't work very well on a platform that
doesn't support pipe(2) or fork(2).
Gisle Vanem wrote:
errno == ENOTCONN is legal according to the man page I quoted (Watt-32
is closer to HP-UX than *BSD/Linux). So Neon should handle that too.
Looking at Lynx, it handles ENOTCONN, EPIPE and ECONNRESET with the same
error message after a failed write. But I understand the distinction on
ECONNRESET.
I found the HP-UX man pages quite vague about which return code should
actually be used. The latest Open Group standard says at
http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_10.html#tag_02_10_14
that:
The SIGPIPE signal shall be sent to a thread that attempts to send
data on a socket that is no longer able to send. In addition, the
send operation fails with the error [EPIPE].
In limited testing on the platforms available to me, with the program
reproduced below:
- Watt-32 gives ENOTCONN on the first write();
- Linux raises SIGPIPE on the second write();
- OS/400 gives EPIPE on the second write(), but doesn't raise a
SIGPIPE exception.
- Cygwin gives ECONNABORTED on the second write(), presumably
because WINSOCK uses WSAECONNABORTED.
Apparently WINSOCK only uses WSAENOTCONN when a socket is used before
connect() or accept(), or when setsockopt() is used to set SO_KEEPALIVE
on a socket that is no longer connected.
I guess Neon could be changed to accept ENOTCONN when using Watt-32.
Here's my test program:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
int main()
{
int c, s, t;
struct sockaddr_in a;
int l = sizeof(a);
if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) perror("socket");
memset(&a, 0, sizeof(a));
a.sin_family = AF_INET;
a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (bind(s, (struct sockaddr *) &a, l)) perror("bind");
if (listen(s, 0)) perror("listen");
if (getsockname(s, (struct sockaddr *) &a, &l)) perror("getsockname");
if ((c = socket(PF_INET, SOCK_STREAM, 0)) == -1) perror("socket");
if (connect(c, (struct sockaddr *) &a, l)) perror("connect");
if ((t = accept(s, NULL, NULL)) == -1) perror("accept");
close(s);
close(t);
if (write(c, "A", 1) == -1) perror("write");
if (write(c, "A", 1) == -1) perror("write");
close(c);
return 0;
}
--
Carey Evans
_______________________________________________
neon mailing list
neon@xxxxxxxxxx
http://mailman.webdav.org/mailman/listinfo/neon
|
|