From: jijiwawa <33614409+jijiwawa@users.noreply.github.com> Date: Sat, 23 Nov 2019 10:24:41 +0000 (+0000) Subject: Bug 5008: SIGBUS in PagePool::level() with custom rock slot size (#515) X-Git-Tag: SQUID_5_0_1~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2a10e977ad4723b0b088dd6111732a1bea03245d;p=thirdparty%2Fsquid.git Bug 5008: SIGBUS in PagePool::level() with custom rock slot size (#515) SMP Squids were crashing on arm64 due to incorrect memory alignment of Ipc::Mem::PagePool::theLevels array. The relative position of the array depends on the number of workers and the number of pages (influenced by the cache capacity and slot size), so some configurations worked OK. We have to manually align manually positioned fields inside shared memory segments. Thankfully, C++11 provides alignment-computing APIs. --- diff --git a/src/ipc/mem/PagePool.cc b/src/ipc/mem/PagePool.cc index c0fb9be3d0..09846c1662 100644 --- a/src/ipc/mem/PagePool.cc +++ b/src/ipc/mem/PagePool.cc @@ -28,7 +28,7 @@ Ipc::Mem::PagePool::PagePool(const char *const id): pageIndex(shm_old(PageStack)(id)), theLevels(reinterpret_cast( reinterpret_cast(pageIndex.getRaw()) + - pageIndex->stackSize())), + pageIndex->stackSize() + pageIndex->levelsPaddingSize())), theBuf(reinterpret_cast(theLevels + PageId::maxPurpose)) { } diff --git a/src/ipc/mem/PagePool.h b/src/ipc/mem/PagePool.h index dd94d60e55..61a433ef12 100644 --- a/src/ipc/mem/PagePool.h +++ b/src/ipc/mem/PagePool.h @@ -49,7 +49,8 @@ public: private: Ipc::Mem::Pointer pageIndex; ///< free pages index - typedef std::atomic Levels_t; + using Levels_t = PageStack::Levels_t; + /// number of shared memory pages used now for each purpose Levels_t * const theLevels; char *const theBuf; ///< pages storage diff --git a/src/ipc/mem/PageStack.cc b/src/ipc/mem/PageStack.cc index 3911fd75de..ccf28d5717 100644 --- a/src/ipc/mem/PageStack.cc +++ b/src/ipc/mem/PageStack.cc @@ -124,7 +124,7 @@ Ipc::Mem::PageStack::SharedMemorySize(const uint32_t, const unsigned int capacit { const size_t levelsSize = PageId::maxPurpose * sizeof(std::atomic); const size_t pagesDataSize = capacity * pageSize; - return StackSize(capacity) + pagesDataSize + levelsSize; + return StackSize(capacity) + LevelsPaddingSize(capacity) + levelsSize + pagesDataSize; } size_t @@ -139,3 +139,10 @@ Ipc::Mem::PageStack::stackSize() const return StackSize(theCapacity); } +size_t +Ipc::Mem::PageStack::LevelsPaddingSize(const unsigned int capacity) +{ + const auto displacement = StackSize(capacity) % alignof(Levels_t); + return displacement ? alignof(Levels_t) - displacement : 0; +} + diff --git a/src/ipc/mem/PageStack.h b/src/ipc/mem/PageStack.h index 6dc442b2c6..5873a62254 100644 --- a/src/ipc/mem/PageStack.h +++ b/src/ipc/mem/PageStack.h @@ -28,6 +28,7 @@ class PageStack { public: typedef uint32_t Value; ///< stack item type (a free page number) + typedef std::atomic Levels_t; PageStack(const uint32_t aPoolId, const unsigned int aCapacity, const size_t aPageSize); @@ -52,6 +53,10 @@ public: static size_t StackSize(const unsigned int capacity); size_t stackSize() const; + /// \returns the number of padding bytes to align PagePool::theLevels array + static size_t LevelsPaddingSize(const unsigned int capacity); + size_t levelsPaddingSize() const { return LevelsPaddingSize(theCapacity); } + private: /// stack index and size type (may temporary go negative) typedef int Offset;