Bug#1001299: visp: FTBFS with glibc 2.34

Steve Langasek steve.langasek at canonical.com
Tue Dec 7 23:26:45 GMT 2021


Package: visp
Version: 3.4.0-4
Severity: important
Tags: patch
User: ubuntu-devel at lists.ubuntu.com
Usertags: origin-ubuntu jammy ubuntu-patch

Dear maintainers,

In Ubuntu, we have upgraded to glibc 2.34.  As a result, visp now fails to
build because MINSIGSTKSZ is no longer a constant but expands to a runtime
call to sysconf(), and the visp source assumes it's a constant.

I found an upstream patch for this in Catch, which is where the code in visp
was copied from, and have adapted it to apply to the visp source.  The
attached patch fixes the compile failure with glibc 2.34.

This is obviously not critical yet for Debian, which still only has glibc
2.33 in experimental.

Unfortunately, even after applying this patch, visp still FTBFS in Ubuntu
with a large number of test failures:

[...]
23% tests passed, 218 tests failed out of 282

Total Test time (real) =  40.88 sec

The following tests FAILED:
	  3 - perfColorConversion (Subprocess aborted)
[...]

These failures are not reproducible on sid with or without the patch for
glibc 2.34 compatibility, but for the moment they block having a fixed visp
in Ubuntu.

-- 
Steve Langasek                   Give me a lever long enough and a Free OS
Debian Developer                   to set it on, and I can move the world.
Ubuntu Developer                                   https://www.debian.org/
slangasek at ubuntu.com                                     vorlon at debian.org
-------------- next part --------------
diff -Nru visp-3.4.0/debian/patches/glibc-2.34.patch visp-3.4.0/debian/patches/glibc-2.34.patch
--- visp-3.4.0/debian/patches/glibc-2.34.patch	1969-12-31 16:00:00.000000000 -0800
+++ visp-3.4.0/debian/patches/glibc-2.34.patch	2021-12-07 13:58:05.000000000 -0800
@@ -0,0 +1,297 @@
+Description: compatibility with glibc 2.34
+ Taken from catch2 upstream, commit id
+ c0d0a50bdb2ae2f749443c0386c2b25379bdbf76 in
+ https://github.com/catchorg/Catch2.
+Author: Steve Langasek <steve.langasek at ubuntu.com>
+Last-Update: 2021-12-07
+
+Index: visp-3.4.0/3rdparty/catch2/catch.hpp
+===================================================================
+--- visp-3.4.0.orig/3rdparty/catch2/catch.hpp
++++ visp-3.4.0/3rdparty/catch2/catch.hpp
+@@ -7688,56 +7688,60 @@
+ #endif // defined(CATCH_PLATFORM_WINDOWS)
+ 
+ // end catch_windows_h_proxy.h
+-#if defined( CATCH_CONFIG_WINDOWS_SEH )
++#include <cassert>
+ 
+ namespace Catch {
+ 
+-    struct FatalConditionHandler {
+-
+-        static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
++    /**
++     * Wrapper for platform-specific fatal error (signals/SEH) handlers
++     *
++     * Tries to be cooperative with other handlers, and not step over
++     * other handlers. This means that unknown structured exceptions
++     * are passed on, previous signal handlers are called, and so on.
++     *
++     * Can only be instantiated once, and assumes that once a signal
++     * is caught, the binary will end up terminating. Thus, there
++     */
++    class FatalConditionHandler {
++        bool m_started = false;
++
++        // Install/disengage implementation for specific platform.
++        // Should be if-defed to work on current platform, can assume
++        // engage-disengage 1:1 pairing.
++        void engage_platform();
++        void disengage_platform();
++    public:
++        // Should also have platform-specific implementations as needed
+         FatalConditionHandler();
+-        static void reset();
+         ~FatalConditionHandler();
+ 
+-    private:
+-        static bool isSet;
+-        static ULONG guaranteeSize;
+-        static PVOID exceptionHandlerHandle;
+-    };
+-
+-} // namespace Catch
+-
+-#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
+-
+-#include <signal.h>
+-
+-namespace Catch {
+-
+-    struct FatalConditionHandler {
+-
+-        static bool isSet;
+-        static struct sigaction oldSigActions[];
+-        static stack_t oldSigStack;
+-        static char altStackMem[];
+-
+-        static void handleSignal( int sig );
++        void engage() {
++            assert(!m_started && "Handler cannot be installed twice.");
++            m_started = true;
++            engage_platform();
++        }
+ 
+-        FatalConditionHandler();
+-        ~FatalConditionHandler();
+-        static void reset();
++        void disengage() {
++            assert(m_started && "Handler cannot be uninstalled without being installed first");
++            m_started = false;
++            disengage_platform();
++        }
+     };
+ 
+-} // namespace Catch
+-
+-#else
+-
+-namespace Catch {
+-    struct FatalConditionHandler {
+-        void reset();
++    //! Simple RAII guard for (dis)engaging the FatalConditionHandler
++    class FatalConditionHandlerGuard {
++        FatalConditionHandler* m_handler;
++    public:
++        FatalConditionHandlerGuard(FatalConditionHandler* handler):
++            m_handler(handler) {
++            m_handler->engage();
++        }
++        ~FatalConditionHandlerGuard() {
++            m_handler->disengage();
++        }
+     };
+-}
+ 
+-#endif
++} // end namespace Catch
+ 
+ // end catch_fatal_condition.h
+ #include <string>
+@@ -7862,6 +7866,7 @@
+         AssertionInfo m_lastAssertionInfo;
+         std::vector<SectionEndInfo> m_unfinishedSections;
+         std::vector<ITracker*> m_activeSections;
++        FatalConditionHandler m_fatalConditionhandler;
+         TrackerContext m_trackerContext;
+         bool m_lastAssertionPassed = false;
+         bool m_shouldReportUnexpected = true;
+@@ -10366,19 +10371,19 @@
+ // end catch_exception_translator_registry.cpp
+ // start catch_fatal_condition.cpp
+ 
+-#if defined(__GNUC__)
+-#    pragma GCC diagnostic push
+-#    pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+-#endif
+-
+ #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
+ 
+ namespace {
+-    // Report the error condition
++    //! Signals fatal error message to the run context
+     void reportFatal( char const * const message ) {
+         Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
+     }
+-}
++
++    //! Minimal size Catch2 needs for its own fatal error handling.
++    //! Picked empirically, so it might not be sufficient on all
++    //! platforms, and for all configurations.
++    constexpr std::size_t minStackSizeForErrors = 32 * 1024;
++} // end unnamed namespace
+ 
+ #endif // signals/SEH handling
+ 
+@@ -10429,10 +10434,6 @@
+         }
+     }
+ 
+-    FatalConditionHandler::~FatalConditionHandler() {
+-        reset();
+-    }
+-
+ bool FatalConditionHandler::isSet = false;
+ ULONG FatalConditionHandler::guaranteeSize = 0;
+ PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
+@@ -10441,6 +10442,8 @@
+ 
+ #elif defined( CATCH_CONFIG_POSIX_SIGNALS )
+ 
++#include <signal.h>
++
+ namespace Catch {
+ 
+     struct SignalDefs {
+@@ -10448,10 +10451,6 @@
+         const char* name;
+     };
+ 
+-    // 32kb for the alternate stack seems to be sufficient. However, this value
+-    // is experimentally determined, so that's not guaranteed.
+-    static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
+-
+     static SignalDefs signalDefs[] = {
+         { SIGINT,  "SIGINT - Terminal interrupt signal" },
+         { SIGILL,  "SIGILL - Illegal instruction signal" },
+@@ -10461,7 +10460,32 @@
+         { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
+     };
+ 
+-    void FatalConditionHandler::handleSignal( int sig ) {
++// Older GCCs trigger -Wmissing-field-initializers for T foo = {}
++// which is zero initialization, but not explicit. We want to avoid
++// that.
++#if defined(__GNUC__)
++#    pragma GCC diagnostic push
++#    pragma GCC diagnostic ignored "-Wmissing-field-initializers"
++#endif
++
++    static char* altStackMem = nullptr;
++    static std::size_t altStackSize = 0;
++    static stack_t oldSigStack{};
++    static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
++
++    static void restorePreviousSignalHandlers() {
++        // We set signal handlers back to the previous ones. Hopefully
++        // nobody overwrote them in the meantime, and doesn't expect
++        // their signal handlers to live past ours given that they
++        // installed them after ours..
++        for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
++            sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
++        }
++        // Return the old stack
++        sigaltstack(&oldSigStack, nullptr);
++    }
++
++    static void handleSignal( int sig ) {
+         char const * name = "<unknown signal>";
+         for (auto const& def : signalDefs) {
+             if (sig == def.id) {
+@@ -10469,16 +10493,33 @@
+                 break;
+             }
+         }
+-        reset();
+-        reportFatal(name);
++        // We need to restore previous signal handlers and let them do
++        // their thing, so that the users can have the debugger break
++        // when a signal is raised, and so on.
++        restorePreviousSignalHandlers();
++        reportFatal( name );
+         raise( sig );
+     }
+ 
+     FatalConditionHandler::FatalConditionHandler() {
+-        isSet = true;
++        assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
++        if (altStackSize == 0) {
++            altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
++        }
++        altStackMem = new char[altStackSize]();
++    }
++
++    FatalConditionHandler::~FatalConditionHandler() {
++        delete[] altStackMem;
++        // We signal that another instance can be constructed by zeroing
++        // out the pointer.
++        altStackMem = nullptr;
++    }
++
++    void FatalConditionHandler::engage_platform() {
+         stack_t sigStack;
+         sigStack.ss_sp = altStackMem;
+-        sigStack.ss_size = sigStackSize;
++        sigStack.ss_size = altStackSize;
+         sigStack.ss_flags = 0;
+         sigaltstack(&sigStack, &oldSigStack);
+         struct sigaction sa = { };
+@@ -10490,29 +10531,16 @@
+         }
+     }
+ 
+-    FatalConditionHandler::~FatalConditionHandler() {
+-        reset();
+-    }
+-
+-    void FatalConditionHandler::reset() {
+-        if( isSet ) {
+-            // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
+-            for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
+-                sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
+-            }
+-            // Return the old stack
+-            sigaltstack(&oldSigStack, nullptr);
+-            isSet = false;
+-        }
+-    }
++#if defined(__GNUC__)
++#    pragma GCC diagnostic pop
++#endif
+ 
+-    bool FatalConditionHandler::isSet = false;
+-    struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
+-    stack_t FatalConditionHandler::oldSigStack = {};
+-    char FatalConditionHandler::altStackMem[sigStackSize] = {};
+ 
+-} // namespace Catch
++    void FatalConditionHandler::disengage_platform() {
++        restorePreviousSignalHandlers();
++    }
+ 
++} // end namespace Catch
+ #else
+ 
+ namespace Catch {
+@@ -12402,9 +12430,8 @@
+     }
+ 
+     void RunContext::invokeActiveTestCase() {
+-        FatalConditionHandler fatalConditionHandler; // Handle signals
++        FatalConditionHandlerGuard _(&m_fatalConditionhandler);
+         m_activeTestCase->invoke();
+-        fatalConditionHandler.reset();
+     }
+ 
+     void RunContext::handleUnfinishedSections() {
diff -Nru visp-3.4.0/debian/patches/series visp-3.4.0/debian/patches/series
--- visp-3.4.0/debian/patches/series	2021-04-20 06:20:29.000000000 -0700
+++ visp-3.4.0/debian/patches/series	2021-12-07 13:57:19.000000000 -0800
@@ -2,3 +2,4 @@
 0002-Increase-threshold-in-testGenericTracker-KLT-for-Deb.patch
 0003-Relax-apriltag-test-threshold-when-lapack-is-used.patch
 0004-Add-dependencies-to-visp_doc-target.patch
+glibc-2.34.patch


More information about the debian-science-maintainers mailing list