Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Jul 2014 11:02:43 -0700
From:      Adrian Chadd <adrian@freebsd.org>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        FreeBSD Net <freebsd-net@freebsd.org>, Dmitry Sivachenko <trtrmitya@gmail.com>
Subject:   Re: does setsockopt(SO_RCVTIMEO) work?
Message-ID:  <CAJ-VmomitYf6N=6tt4pno25VO8oS0KHGQMoobCZtS%2BNk%2BN%2BSBA@mail.gmail.com>
In-Reply-To: <20140716223814.O2597@besplex.bde.org>
References:  <F6D31298-F070-4CB8-ADFF-243302A6CE1E@gmail.com> <20140716223814.O2597@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
I'm about to bump into this - would you be able to put together a
patch to address these issues? That way I can also test it out with
the UDP stuff I'm working on and get it into the tree.

Thanks,


-a


On 16 July 2014 06:24, Bruce Evans <brde@optusnet.com.au> wrote:
> On Wed, 16 Jul 2014, Dmitry Sivachenko wrote:
>
>> I am having trouble using {g,s}etsockopt(SO_RCVTIMEO).  Consider the
>> following small test program.
>> I expect to retrieve the value of 1 second via getsockopt call, I expect
>> the following output:
>> tv_sec=1, tv_usec=0
>> But I actually get
>> tv_sec=0, tv_usec=0
>>
>> What am I missing?
>>
>> Thanks!
>>
>> PS: on Linux it works as I expect.
>
>
> On old versions of FreeBSD it works as expected.
>
> This was broken last year.  I pointed out the bug and many others in my
> review, but it is still there.  From the review:
>
> @ On Sun, 1 Sep 2013, Davide Italiano wrote:
> @ @ > Log:
> @ >  Fix socket buffer timeouts precision using the new sbintime_t KPI
> instead
> @ >  of relying on the tvtohz() workaround. The latter has been introduced
> @ >  lately by jhb@ (r254699) in order to have a fix that can be backported
> @ >  to STABLE.
> @ >
> @ >  Reported by:       Vitja Makarov <vitja.makarov at gmail dot com>
> @ >  Reviewed by:       jhb (earlier version)
> @ @ This reintroduces overflow bugs that were fixed by using tvtohz().
> tvtohz()
> @ clamps the value to INT_MAX instead of overflowing, but tvtosbt() just
> @ overflows.
>
> These bugs are small (they are are only for timevals larger than INT_MAX
> seconds, which can only occur on systems with bloated 64-bit time_t's),
> but they were fixed long ago.
>
> @ @ This gives much larger overflow bugs in getsockopt().
>
> This bug is still there.  So in your test program, the timeout is set
> correctly, but it is returned as 0 after overflow of a large value
> gives 0.  All values larger than 1 second are truncated to less than
> 1 second.
>
> I expected more garbage in the values for timevals between 0.5 seconds
> (inclusive) and 1.0 seconds (not inclusive).  I think they would happen
> for the corresonding bug in setsockopt(), but in getsockopt() there is
> only a small (but annoying) rounding error.  I tried a timeval of
> 0 seconds, 500000 microseconds.  This was returned as 0 seconds,
> 499999 microseconds.  This rounding error happens because almost no values
> in the power-of-10 time scale for timevals can be represented in the
> power-of-2 time scale for sbintimes.  The rounding is always down, so
> conversion back and forth drops 1 ULP in almost all cases.  bintime
> gives similar errors.  sys/time.h has a large comment defending this
> bug.
>
> @ @ > ...
> @ > Modified: head/sys/kern/uipc_socket.c
> @ >
> ==============================================================================
> @ > --- head/sys/kern/uipc_socket.c     Sun Sep  1 23:06:28 2013
> (r255137)
> @ > +++ head/sys/kern/uipc_socket.c     Sun Sep  1 23:34:53 2013
> (r255138)
> @ > @@ -2541,7 +2541,7 @@ sosetopt(struct socket *so, struct socko
> @ >     int     error, optval;
> @ >     struct  linger l;
> @ >     struct  timeval tv;
> @ > -   u_long  val;
> @ > +   sbintime_t val;
> @ >     uint32_t val32;
> @ > #ifdef MAC
> @ >     struct mac extmac;
> @ @ This fixes a style bug (type error) that should have been fixed in the
> @ previous commit.  'int optval' is used for most options, but the old
> @ code needed `u_long val' for its home made conversion.  u_long became
> @ unnecessary and the extra variable became bogus when tvtohz() was used,
> @ since optval can hold tvtohz().
> @ @ > @@ -2703,7 +2703,7 @@ sosetopt(struct socket *so, struct socko
> @ >                             error = EDOM;
> @ >                             goto bad;
> @ >                     }
> @ @ There used to be more range checking above here.  Some was moved into
> @ tvtohz().  Changing to tvtosbt() moves it to /dev/null.
> @ @ > -                 val = tvtohz(&tv);
> @ > +                   val = tvtosbt(tv);
> @ >
> @ >                     switch (sopt->sopt_name) {
> @ >                     case SO_SNDTIMEO:
> @ @ optval can't hold tvtosbt(), so an extra variable is not a large style
> @ bug now.  But it can be avoided here by doing 2 assignments of tvtosbt()
> @ to so_snd/rcv.sb_timeout.
>
> 'val' _can_ hold tvtosbt() (it was enlarged to do this), so there is only
> a far-off overflow bug here (when tvtosbt() overflows internally)).
>
> @ @ > @@ -2857,8 +2857,7 @@ integer:
> @ >                     optval = (sopt->sopt_name == SO_SNDTIMEO ?
> @ >                               so->so_snd.sb_timeo :
> so->so_rcv.sb_timeo);
> @ @ This is now very broken.  optval is only int, so it can't hold the
> 64-bit
> @ sbintime_t.  I think it can hold times less than 0.5 seconds.  Overflow
> @ starts at 0.5 seconds by giving sign extension bugs on 2's complement
> machines.
> @ @ Style bug: non-KNF indentation.
>
> This still has all its bugs and style bugs.
>
> @ @ >
> @ @ Style bug: extra blank line separates related code.
> @ @ > -                 tv.tv_sec = optval / hz;
> @ > -                   tv.tv_usec = (optval % hz) * tick;
> @ > +                   tv = sbttotv(optval);
> @ @ This together with the style can be fixed by 2 assignments also (1
> @ assignment in the conditional operater also fixes verbosenes):
> @ @                     tv = sbttotv(sopt->sopt_name == SO_SNDTIMEO ?
> @                           so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
>
> Fix for the main bug some style bugs.
>
> [... 200 more lines with further duscussion of style and overflow bugs]
>
> Bruce
>
> _______________________________________________
> freebsd-net@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-net
> To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org"



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ-VmomitYf6N=6tt4pno25VO8oS0KHGQMoobCZtS%2BNk%2BN%2BSBA>