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>