]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Name shared memory segments in a more portable way
authorAlex Rousskov <rousskov@measurement-factory.com>
Wed, 26 Oct 2011 16:33:46 +0000 (10:33 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Wed, 26 Oct 2011 16:33:46 +0000 (10:33 -0600)
to make shm_open() work on FreeBSD and some other OSes.

Linux and friends use "/slashless-name" template for shared memory segment IDs.
HPUX and friends use "/full/path/to/some/file".
FreeBSD uses the former or the latter, depending on version and jail context.

We now distinguish the above cases and prefix the internal segment ID
accordingly. The above analysis and its implementation are based on the
boost::interprocess code.

To make matters worse, the right prefix for path-based OSes depends on whether
we are running an [installed] Squid binary or just a "make check" test case.
For test cases, we cannot use PREFIX-based paths because they may not exist.
Instead, we use the current directory. This is consistent with TESTDIR (i.e.,
cache_dir location) which each fs test case defines to be in the current
directory.

Finally, the segment name may clash with cache_dir name on path-based OSes. We
now append ".shm" to the segment name to reduce the likelihood of a collision.
TODO: Should StoreMap/etc (or their creators) append "map"/etc to their IDs?

CREDITS
compat/Makefile.am
compat/shm.cc [new file with mode: 0644]
compat/shm.h
src/ipc/mem/Segment.cc
src/ipc/mem/Segment.h
src/tests/testRock.cc

diff --git a/CREDITS b/CREDITS
index e6c4887db1234a124f0006e1ab377c100cbdc608..b115ff1a0b0e86c7626db8e240858561f61e5ef9 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -570,3 +570,36 @@ icons/silk/:
     documentation for the software which includes the set or a subset
     of the icons contained within. 
 
+==============================================================================
+
+shm_portable_segment_name_is_path() implementation:
+
+  Derived from boost/interprocess/shared_memory_object.hpp and
+      boost/interprocess/detail/workaround.hpp at http://www.boost.org/
+
+  (C) Copyright Ion Gaztanaga 2005-2009.
+  Distributed under the Boost Software License, Version 1.0
+
+  Boost Software License - Version 1.0 - August 17th, 2003
+
+  Permission is hereby granted, free of charge, to any person or organization
+  obtaining a copy of the software and accompanying documentation covered by
+  this license (the "Software") to use, reproduce, display, distribute,
+  execute, and transmit the Software, and to prepare derivative works of the
+  Software, and to permit third-parties to whom the Software is furnished to
+  do so, all subject to the following:
+
+  The copyright notices in the Software and this entire statement, including
+  the above license grant, this restriction and the following disclaimer,
+  must be included in all copies of the Software, in whole or in part, and
+  all derivative works of the Software, unless such copies or derivative
+  works are solely in the form of machine-executable object code generated by
+  a source language processor.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+  SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+  FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+  DEALINGS IN THE SOFTWARE.
index 8667bb0c65852c165d2b84e71430119e6f8bb4e6..7b3f7b8cfc89d33a5c4602b6a9682ed51cdd446d 100644 (file)
@@ -32,6 +32,7 @@ libcompat_squid_a_SOURCES = \
        initgroups.h \
        osdetect.h \
        psignal.h \
+       shm.cc \
        shm.h \
        stdio.h \
        stdvarargs.h \
diff --git a/compat/shm.cc b/compat/shm.cc
new file mode 100644 (file)
index 0000000..431df0a
--- /dev/null
@@ -0,0 +1,28 @@
+#include "config.h"
+#include "compat/shm.h"
+
+#if defined(__FreeBSD__) && (__FreeBSD__ >= 7)
+#    include <sys/sysctl.h>
+#endif
+
+
+/*
+ * Some systems have filesystem-based resources and interpret segment names
+ * as file paths. The so-called 'portable' "/name" format does not work well 
+ * for them. And, according to Boost::interprocess, recent FreeBSD versions
+ * make this decision depending on whether the shm_open() caller is jailed!
+ */
+bool
+shm_portable_segment_name_is_path()
+{
+#if defined(_SQUID_HPUX_) || defined(_SQUID_OSF_) || defined(__vms) || (defined(_SQUID_FREEBSD_) && (__FreeBSD__ < 7))
+       return true;
+#elif defined(_SQUID_FREEBSD_)
+   int jailed = 0;
+   size_t len = sizeof(jailed);
+   ::sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0);
+   return !jailed;
+#else
+    return false;
+#endif
+}
index c9135d5969eef750e6afd8c63d7a1609b9f71520..873a44c40d7b3938fcc5fabc55c34e31378527de 100644 (file)
@@ -42,4 +42,8 @@ extern "C" {
 
 #endif /* HAVE_SHM */
 
+
+/// Determines whether segment names are iterpreted as full file paths.
+bool shm_portable_segment_name_is_path();
+
 #endif /* SQUID_COMPAT_CPU_H */
index 00b4f61a9453ebba38d93feca3bbc31d77fe1a65..c9bee080ffdf70408a2556b5297c1d53f1f8d2f1 100644 (file)
 #include <sys/stat.h>
 #include <unistd.h>
 
+
+// test cases change this
+const char *Ipc::Mem::Segment::BasePath = DEFAULT_STATEDIR;
+
 void *
 Ipc::Mem::Segment::reserve(size_t chunkSize)
 {
@@ -169,11 +173,16 @@ Ipc::Mem::Segment::statSize(const char *context) const
     return s.st_size;
 }
 
-/// Generate name for shared memory segment. Replaces all slashes with dots.
+/// Generate name for shared memory segment. Starts with a prefix required
+/// for cross-platform portability and replaces all slashes in ID with dots.
 String
 Ipc::Mem::Segment::GenerateName(const char *id)
 {
-    String name("/squid-");
+    assert(BasePath);
+    static const bool nameIsPath = shm_portable_segment_name_is_path();
+    String name(nameIsPath ? BasePath : "/squid-");
+
+    // append id, replacing slashes with dots
     for (const char *slash = strchr(id, '/'); slash; slash = strchr(id, '/')) {
         if (id != slash) {
             name.append(id, slash - id);
@@ -182,6 +191,8 @@ Ipc::Mem::Segment::GenerateName(const char *id)
         id = slash + 1;
     }
     name.append(id);
+
+    name.append(".shm"); // to distinguish from non-segments when nameIsPath
     return name;
 }
 
index 28966f298fb57d66b6702a2e99cd723446d70333..b8e36f04b19dbdb1f847afbe1f60f7f7ea93da34 100644 (file)
@@ -35,6 +35,8 @@ public:
     void *mem() { return reserve(0); } ///< pointer to the next chunk
     void *reserve(size_t chunkSize); ///< reserve and return the next chunk
 
+    /// common path of all segment names in path-based environments
+    static const char *BasePath;
 
 private:
 
index e8f62b1c0a77eb6a0c0f559f3aaa5df1b7378b17..600fe828dc712bf9cad027d8fd2702e132bfccbe 100644 (file)
@@ -40,6 +40,9 @@ testRock::setUp()
     if (0 > system ("rm -rf " TESTDIR))
         throw std::runtime_error("Failed to clean test work directory");
 
+    // use current directory for shared segments (on path-based OSes)
+    Ipc::Mem::Segment::BasePath = "";
+
     Store::Root(new StoreController);
 
     store = new Rock::SwapDir();