]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug 5008: SIGBUS in PagePool::level() with custom rock slot size (#515)
authorjijiwawa <33614409+jijiwawa@users.noreply.github.com>
Sat, 23 Nov 2019 10:24:41 +0000 (10:24 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Sat, 23 Nov 2019 12:41:15 +0000 (12:41 +0000)
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.

src/ipc/mem/PagePool.cc
src/ipc/mem/PagePool.h
src/ipc/mem/PageStack.cc
src/ipc/mem/PageStack.h

index c0fb9be3d08093b45dbe7c4af4b2578b4c3755dc..09846c1662f9736882c24634dbcd3898108e7fcc 100644 (file)
@@ -28,7 +28,7 @@ Ipc::Mem::PagePool::PagePool(const char *const id):
     pageIndex(shm_old(PageStack)(id)),
     theLevels(reinterpret_cast<Levels_t *>(
                   reinterpret_cast<char *>(pageIndex.getRaw()) +
-                  pageIndex->stackSize())),
+                  pageIndex->stackSize() + pageIndex->levelsPaddingSize())),
     theBuf(reinterpret_cast<char *>(theLevels + PageId::maxPurpose))
 {
 }
index dd94d60e55a07f2e726c38888e518e4ce177323d..61a433ef12ef8495cdf002942f465f76de270bd5 100644 (file)
@@ -49,7 +49,8 @@ public:
 
 private:
     Ipc::Mem::Pointer<PageStack> pageIndex; ///< free pages index
-    typedef std::atomic<size_t> 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
index 3911fd75de27488022b8b51f4d9753cd4ac5911e..ccf28d5717be524d1de9cc3c0c40655577052f85 100644 (file)
@@ -124,7 +124,7 @@ Ipc::Mem::PageStack::SharedMemorySize(const uint32_t, const unsigned int capacit
 {
     const size_t levelsSize = PageId::maxPurpose * sizeof(std::atomic<Ipc::Mem::PageStack::Value>);
     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;
+}
+
index 6dc442b2c635812408e897eacbd22cf7a9ce9a7c..5873a6225444c888c4c3d3e2b9edde621b1709c4 100644 (file)
@@ -28,6 +28,7 @@ class PageStack
 {
 public:
     typedef uint32_t Value; ///< stack item type (a free page number)
+    typedef std::atomic<size_t> 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;