Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Feb 2012 01:07:21 +0200
From:      Andriy Gapon <avg@FreeBSD.org>
To:        Alex Dupre <ale@FreeBSD.org>
Cc:        hackers@FreeBSD.org
Subject:   outdated/dangerous code in databases/mysql50-server
Message-ID:  <4F4180A9.3070400@FreeBSD.org>

next in thread | raw e-mail | index | archive | help

Alex,

sql/mysqld.cc has the following code:
inline void setup_fpu()
{
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
  /* We can't handle floating point exceptions with threads, so disable
     this on freebsd
     Don't fall for overflow, underflow,divide-by-zero or loss of precision
  */
#if defined(__i386__)
  fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
              FP_X_IMP));
#else
  fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
              FP_X_IMP));
#endif /* __i386__ */
#endif /* __FreeBSD__ && HAVE_IEEEFP_H */

First of all the code seems to be rather ancient.  Probably as a result of this
it uses a rather potentially dangerous fpsetmask() calls.

Second, I am not sure to what problem [with FreeBSD threads] the comment refers.
 I am quite sure that there is no such problem in the supported releases.

Third, the default state of mxcsr (FPU/SSE control and status register) on
FreeBSD is to have all those exceptions disabled.

Last and the most important, the !__i386__ case omits FP_X_DNML, which means
that on e.g. amd64 the denormalized floating point numbers can cause an
exception.  And that is not really expected by any code.

Also, it is not guaranteed that this call (as a part mysql client
initialization) would be made in some special dedicated mysql thread.

In 5.1 and 5.5 this piece code looks a bit smarter:
inline void setup_fpu()
{
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
  /* We can't handle floating point exceptions with threads, so disable
     this on freebsd
     Don't fall for overflow, underflow,divide-by-zero or loss of precision.
     fpsetmask() is deprecated in favor of fedisableexcept() in C99.
  */
#if defined(FP_X_DNML)
  fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
              FP_X_IMP));
#else
  fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
              FP_X_IMP));
#endif /* FP_X_DNML */
#endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */

#ifdef HAVE_FEDISABLEEXCEPT
  fedisableexcept(FE_ALL_EXCEPT);
#endif

I guess that this version should be OK, because FreeBSD has fedisableexcept for
a long time (I think) and so the safer call should be used on all archs.


On mysql "client side" the setup_fpu call is made from init_server_components,
which in turn is called from init_embedded_server, so the problem is relevant
for embedded mysql case.  It is relevant for mysql server too, of course.

-- 
Andriy Gapon



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4F4180A9.3070400>