Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-36510

InnoDB fails to compile with clang++-20

Details

    Description

      When I try to compile MariaDB Server without cmake -DPLUGIN_PERFSCHEMA=NO using Clang 20, the compilation will fail on the instantiation of purge_sys_t::unordered_map as follows:

      10.11 669f719cc21286020c95eec11f0d09b74f96639e

      In file included from /mariadb/10.11/storage/innobase/trx/trx0purge.cc:27:
      In file included from /mariadb/10.11/storage/innobase/include/trx0purge.h:29:
      In file included from /mariadb/10.11/storage/innobase/include/trx0sys.h:28:
      In file included from /mariadb/10.11/storage/innobase/include/buf0buf.h:32:
      In file included from /mariadb/10.11/storage/innobase/include/fil0fil.h:30:
      In file included from /mariadb/10.11/storage/innobase/include/mach0data.h:32:
      In file included from /mariadb/10.11/storage/innobase/include/mtr0types.h:29:
      In file included from /mariadb/10.11/storage/innobase/include/buf0types.h:181:
      In file included from /mariadb/10.11/storage/innobase/include/sux_lock.h:20:
      In file included from /mariadb/10.11/storage/innobase/include/srw_lock.h:580:
      In file included from /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/unordered_set:43:
      In file included from /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/bits/unordered_set.h:33:
      In file included from /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/bits/hashtable.h:37:
      /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/bits/hashtable_policy.h:1475:76: error: chosen constructor is explicit in copy-initialization

      This could be fixed by the following:

      diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h
      index 3ff5f8853e0..398dd0dcc9e 100644
      --- a/storage/innobase/include/ut0new.h
      +++ b/storage/innobase/include/ut0new.h
      @@ -277,7 +277,6 @@ class ut_allocator {
       
       #ifdef UNIV_PFS_MEMORY
       	/** Default constructor. */
      -	explicit
       	ut_allocator(PSI_memory_key key = PSI_NOT_INSTRUMENTED)
       		: m_key(key)
       	{
      

      Or the following:

      diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h
      index 21ec23817d2..0d5e670aef7 100644
      --- a/storage/innobase/include/trx0purge.h
      +++ b/storage/innobase/include/trx0purge.h
      @@ -124,6 +124,10 @@ class purge_sys_t
       
       
       public:
      +#ifdef UNIV_PFS_MEMORY
      +  purge_sys_t() : pages(PSI_NOT_INSTRUMENTED) {}
      +#endif
      +
         /** latch protecting view, m_enabled */
         alignas(CPU_LEVEL1_DCACHE_LINESIZE)
         mutable IF_DBUG(srw_lock_debug,srw_spin_lock) latch;
      

      Or we could remove the allocator wrapper and start catching std::bad_alloc for better error handling:

      diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h
      index fd355758eba..f68bb39ae34 100644
      --- a/storage/innobase/include/trx0purge.h
      +++ b/storage/innobase/include/trx0purge.h
      @@ -169,14 +169,7 @@ class purge_sys_t
       
         using unordered_map =
           std::unordered_map<const page_id_t, buf_block_t*, hasher,
      -#if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ >= 8
      -                       std::equal_to<page_id_t>
      -                       /* GCC 4.8.5 would fail to find a matching allocator */
      -#else
      -                       std::equal_to<page_id_t>,
      -                       ut_allocator<std::pair<const page_id_t, buf_block_t*>>
      -#endif
      -                       >;
      +                       std::equal_to<page_id_t>>;
         /** map of buffer-fixed undo log pages processed during a purge batch */
         unordered_map pages;
       public:
      

      We are indeed not passing any performance_schema instrumentation key in anything related to purge_sys. The custom allocator does not seem to add much value. Allocation is happening in the following:

      buf_block_t *purge_sys_t::get_page(page_id_t id)
      {
        ut_ad(!recv_sys.recovery_on);
       
        buf_block_t *&h= pages[id];
      

      and possibly in the following:

      void purge_sys_t::batch_cleanup(const purge_sys_t::iterator &head)
      {
        m_active= false;
       
        /* Release the undo pages. */
        for (auto p : pages)
          p.second->unfix();
        pages.clear();
        pages.reserve(srv_purge_batch_size);
      

      Attachments

        Issue Links

          Activity

            serg, what do you think would be the most appropriate solution here?

            marko Marko Mäkelä added a comment - serg , what do you think would be the most appropriate solution here?

            What does explicit mean here? I read it as "you cannot do a copy assignment, you must explicitly specify PSI key every time". I don't understand why it should be the case, it seems fairly logical that if you can copy ut_allocator then the copy will have the same key. That is, I'd remove explciit

            serg Sergei Golubchik added a comment - What does explicit mean here? I read it as "you cannot do a copy assignment, you must explicitly specify PSI key every time". I don't understand why it should be the case, it seems fairly logical that if you can copy ut_allocator then the copy will have the same key. That is, I'd remove explciit

            serg, the main question is whether there is any point or benefit in invoking the performance_schema wrapper interface if the "instrumentation key" is always specified as PSI_NOT_INSTRUMENTED. If there is none, I would prefer to avoid specifying an allocator template.

            marko Marko Mäkelä added a comment - serg , the main question is whether there is any point or benefit in invoking the performance_schema wrapper interface if the "instrumentation key" is always specified as PSI_NOT_INSTRUMENTED . If there is none, I would prefer to avoid specifying an allocator template.

            if you don't think it'll be instrumented anytime soon — feel free to remove it, of course

            serg Sergei Golubchik added a comment - if you don't think it'll be instrumented anytime soon — feel free to remove it, of course
            marko Marko Mäkelä added a comment -

            If we instantiated the std::unordered_map with the default allocator, the handling of running out of memory would be different. Either the program would terminate because of an uncaught std::bad_alloc, or we could make purge_sys_t::get_page() return nullptr, which would lead into silently skipping the purge of some committed history. Such silent skipping is reasonable when the function returns nullptr due to data corruption. But it would seem to be inappropriate to start introducing a form of corruption when we happen to run out of memory. In that rare case, it should be better to kill and restart the mariadbd process to get rid of some memory leak or fragmentation.

            I implemented the simplest and least risky option: removing the explicit keyword from ut_allocator<T,bool>::ut_allocator(PSI_memory_key).

            marko Marko Mäkelä added a comment - If we instantiated the std::unordered_map with the default allocator, the handling of running out of memory would be different. Either the program would terminate because of an uncaught std::bad_alloc , or we could make purge_sys_t::get_page() return nullptr , which would lead into silently skipping the purge of some committed history. Such silent skipping is reasonable when the function returns nullptr due to data corruption. But it would seem to be inappropriate to start introducing a form of corruption when we happen to run out of memory. In that rare case, it should be better to kill and restart the mariadbd process to get rid of some memory leak or fragmentation. I implemented the simplest and least risky option: removing the explicit keyword from ut_allocator<T,bool>::ut_allocator(PSI_memory_key) .

            People

              marko Marko Mäkelä
              marko Marko Mäkelä
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.