Opened 4 years ago

Last modified 4 years ago

#13632 new Bugs

boost::function operator== is bugged on FreeBSD 11.2

Reported by: hongli@… Owned by: Douglas Gregor
Milestone: To Be Determined Component: function
Version: Boost 1.67.0 Severity: Problem
Keywords: Cc:

Description

The Passenger application server is a C++ application and uses Boost. Our FreeBSD 11.2 users ran into a crash bug: https://github.com/phusion/passenger/issues/2097

Upon further investigation, it turns out that the underlying problem is boost::function operator==. The following test program...

boost::function<void ()> f;
printf("is null: %d\n", f == NULL);

...prints 1 on macOS (as it should) and 0 on FreeBSD 11.2. I haven't tested this small test program on FreeBSD 11.1, but users reported that Passenger worked fine on FreeBSD 11.1 so the problem likely did not exist there.

Digger deeper, on FreeBSD the == operator calls this function (in boost/function/function_base.hpp):

#  if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
// Comparisons between boost::function objects and arbitrary function
// objects. GCC 3.3 and before has an obnoxious bug that prevents this
// from working.
template<typename Functor>
  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  operator==(const function_base& f, Functor g)
  {
    if (const Functor* fp = f.template target<Functor>())
      return function_equal(*fp, g);
    else return false;
  }

...and returns false (the else branch).

While on macOS it calls this function:

inline bool operator!=(const function_base& f,
                       detail::function::useless_clear_type*)
{
  return !f.empty();
}

Just looking at the #if there already gives me the feeling that it is not right. Boost is trying to work around a GCC 3 bug but it wrongly detects Clang 6.0.0 as GCC 3.

This bug has been confirmed on both Boost 1.64 and Boost 1.67.

Change History (3)

comment:1 by VVD, 4 years ago

FreeBSD 11.1 have clang 4.0.0, but FreeBSD 11.2 have clang 6.0.0. Passenger compiled with GCC 6.4.0 from ports on FreeBSD 11.2 work fine.

Probably boost don't support clang 6.0.0.

Bug reports in other trackers with more information: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=229392 https://github.com/phusion/passenger/issues/2097

comment:2 by anonymous, 4 years ago

Important update. It was discovered that FreeBSD 11.2, as well as recent versions of OpenBSD, promote NULL to nullptr. Comparing an empty boost::function with 0 results in true, but comparing it with nullptr results in false:

boost::function<void ()> f;
printf("is nullptr: %d\n", f == nullptr);
printf("is 0: %d\n", f == 0);

This prints 0 and 1, respectively.

Is this behavior intentional? Are we supposed to be able to compare boost::function with nullptr? Intuitively I would expect == 0 and == nullptr to behave the same.

Note: See TracTickets for help on using tickets.