Date: Wed, 7 Feb 2001 17:47:54 -0800 From: "Jonathan Graehl" <jonathan@graehl.org> To: <freebsd-arch@freebsd.org> Cc: "Jonathan Lemon" <jlemon@freebsd.org> Subject: empirical results of waiting for nonblocking connect with kqueue/EVFILT_WRITE (EV_EOF is not set for timed out connections, bug?) Message-ID: <NCBBLOALCKKINBNNEDDLCEHNDKAA.jonathan@graehl.org>
next in thread | raw e-mail | index | archive | help
cases for the kevent returned from EVFILT_WRITE for socket whose connect
returned error EWOULDBLOCK:
connection failed, refused: flags=0x8001 (= EV_EOF & EV_ADD); data=0x4000
connection failed, timed out (+ any icmp response, host unreachable, host admin
prohibited, etc): flags=0x1 (= EV_ADD); data=0x4000
connection succesful: flags=0x1 = EV_ADD; data=0x43e0 ( = socket buffer bytes
available to write)
if you want to see the particular error code (host or net unreachable, or just
plain timed out) for a timed out connection, you can use
getsockopt(SO_ERROR...). also getpeername can determine if the socket is
connected (is there a more direct socket call to do so?)
question: clearly, the event for a pending connection has these reproducible
(aside from changing the socket send buffer size), undocumented values in the
flags/data fields. what can be counted on (and documented) in the future? for
now, i would use the test e.data != 0x4000, and make sure i don't set my socket
send buffer small enough for any confusion to arise.
i would think that EV_EOF should be set for timed out connections as well as
refused ones, and this should be the documented criteria
my suggestion would be to create a flag EV_SOERR, and change filt_soread and
filt_sowrite (in sys/kern/uipc_socket.c) from:
if (so->so_error) /* temporary udp error */
return (1);
to:
if (so->so_error) {
kn->kn_flags |= EV_SOERR;
kn->kn_data = so->so_error;
return (1);
}
or, to maintain compatibility (if it is necessary to return with no indication
for udp errors?), to:
if (so->so_error) {
if ((so->so_proto->pr_flags & PR_CONNREQUIRED))
kn->kn_flags |= EV_EOF;
return (1);
}
(EV_EOF and/or EV_SOERR would be fine in either case, as long as there is some
indication, although it would be nice to not have to getsockopt(SO_ERR,...))
larger context:
static int
filt_sowrite(struct knote *kn, long hint)
{
struct socket *so = (struct socket *)kn->kn_fp->f_data;
kn->kn_data = sbspace(&so->so_snd);
if (so->so_state & SS_CANTSENDMORE) {
kn->kn_flags |= EV_EOF;
return (1);
}
if (so->so_error) /* temporary udp error */
return (1);
if (((so->so_state & SS_ISCONNECTED) == 0) &&
(so->so_proto->pr_flags & PR_CONNREQUIRED))
return (0);
return (kn->kn_data >= so->so_snd.sb_lowat);
}
disclaimer: i only vaguely understand what's going on ;)
--
Jonathan Graehl
email: jonathan@graehl.org
web: http://jonathan.graehl.org/
phone: 858-642-7562
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?NCBBLOALCKKINBNNEDDLCEHNDKAA.jonathan>
