Skip site navigation (1)Skip section navigation (2)
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>