Opened 4 years ago
Last modified 4 years ago
#13632 new Bugs
boost::function operator== is bugged on FreeBSD 11.2
Reported by: | 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 , 4 years ago
comment:2 by , 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.
comment:3 by , 4 years ago
You can close this bugreport. Detailed explanation is here: https://www.joyfulbikeshedding.com/blog/2018-07-17-do-not-compare-boost-function-with-null.html
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