43 assert(!chunkSize ||
static_cast<off_t
>(chunkSize) > 0);
63 theFD(-1), theName(GenerateName(id)), theMem(nullptr),
64 theSize(0), theReserved(0), doUnlink(false)
72 if (close(theFD) != 0) {
74 debugs(54, 5,
"close " << theName <<
": " <<
xstrerr(xerrno));
100 if (!createFresh(xerrno) && xerrno == EEXIST) {
106 debugs(54, 5,
"shm_open " << theName <<
": " <<
xstrerr(xerrno));
107 fatalf(
"Ipc::Mem::Segment::create failed to shm_open(%s): %s\n",
108 theName.termedBuf(),
xstrerr(xerrno));
111 if (ftruncate(theFD, aSize)) {
114 debugs(54, 5,
"ftruncate " << theName <<
": " <<
xstrerr(xerrno));
115 fatalf(
"Ipc::Mem::Segment::create failed to ftruncate(%s): %s\n",
116 theName.termedBuf(),
xstrerr(xerrno));
120 theSize = statSize(
"Ipc::Mem::Segment::create");
128 debugs(54, 3,
"created " << theName <<
" segment: " << theSize);
137 theFD =
shm_open(theName.termedBuf(), O_RDWR, 0);
140 debugs(54, 5,
"shm_open " << theName <<
": " <<
xstrerr(xerrno));
141 fatalf(
"Ipc::Mem::Segment::open failed to shm_open(%s): %s\n",
142 theName.termedBuf(),
xstrerr(xerrno));
145 theSize = statSize(
"Ipc::Mem::Segment::open");
146 doUnlink = unlinkWhenDone;
148 debugs(54, 3,
"opened " << theName <<
" segment: " << theSize);
156Ipc::Mem::Segment::createFresh(
int &xerrno)
158 theFD =
shm_open(theName.termedBuf(),
159 O_EXCL | O_CREAT | O_RDWR,
167Ipc::Mem::Segment::attach()
174 assert(theSize ==
static_cast<off_t
>(
static_cast<size_t>(theSize)));
177 mmap(
nullptr, theSize, PROT_READ | PROT_WRITE, MAP_SHARED, theFD, 0);
178 if (p == MAP_FAILED) {
180 debugs(54, 5,
"mmap " << theName <<
": " <<
xstrerr(xerrno));
181 fatalf(
"Ipc::Mem::Segment::attach failed to mmap(%s): %s\n",
182 theName.termedBuf(),
xstrerr(xerrno));
191Ipc::Mem::Segment::detach()
196 if (munmap(theMem, theSize)) {
198 debugs(54, 5,
"munmap " << theName <<
": " <<
xstrerr(xerrno));
199 fatalf(
"Ipc::Mem::Segment::detach failed to munmap(%s): %s\n",
200 theName.termedBuf(),
xstrerr(xerrno));
208Ipc::Mem::Segment::lock()
211 debugs(54, 5,
"mlock(2)-ing disabled");
215#if defined(_POSIX_MEMLOCK_RANGE)
216 debugs(54, 7,
"mlock(" << theName <<
',' << theSize <<
") starts");
217 if (mlock(theMem, theSize) != 0) {
218 const int savedError = errno;
219 fatalf(
"shared_memory_locking on but failed to mlock(%s, %" PRId64 "): %s\n",
220 theName.termedBuf(),
static_cast<int64_t
>(theSize),
xstrerr(savedError));
223 debugs(54, 7,
"mlock(" << theName <<
',' << theSize <<
") OK");
225 debugs(54, 5,
"insufficient mlock(2) support");
227 static bool warnedOnce =
false;
230 "honoring `shared_memory_locking on`. " <<
231 "If you lack RAM, kernel will kill Squid later.");
239Ipc::Mem::Segment::unlink()
243 debugs(54, 5,
"shm_unlink(" << theName <<
"): " <<
xstrerr(xerrno));
245 debugs(54, 3,
"unlinked " << theName <<
" segment");
250Ipc::Mem::Segment::statSize(
const char *context)
const
255 memset(&s, 0,
sizeof(s));
257 if (fstat(theFD, &s) != 0) {
259 debugs(54, 5, context <<
" fstat " << theName <<
": " <<
xstrerr(xerrno));
260 fatalf(
"Ipc::Mem::Segment::statSize: %s failed to fstat(%s): %s\n",
261 context, theName.termedBuf(),
xstrerr(xerrno));
270Ipc::Mem::Segment::GenerateName(
const char *
id)
272 assert(BasePath && *BasePath);
277 if (name[name.
size()-1] !=
'/')
286 for (
const char *slash = strchr(
id,
'/'); slash; slash = strchr(
id,
'/')) {
288 name.
append(
id, slash -
id);
307 theName(id), theMem(
NULL), theSize(0), theReserved(0), doUnlink(false)
314 delete []
static_cast<char *
>(theMem);
317 debugs(54, 3,
"unlinked " << theName <<
" fake segment");
332 checkSupport(
"Fake segment creation");
334 const bool inserted =
Segments.insert(std::make_pair(theName,
this)).second;
336 fatalf(
"Duplicate fake segment creation: %s", theName.termedBuf());
338 theMem =
new char[aSize];
342 debugs(54, 3,
"created " << theName <<
" fake segment: " << theSize);
349 checkSupport(
"Fake segment open");
351 const SegmentMap::const_iterator i =
Segments.find(theName);
353 fatalf(
"Fake segment not found: %s", theName.termedBuf());
355 const Segment &segment = *i->second;
359 debugs(54, 3,
"opened " << theName <<
" fake segment: " << theSize);
367 ": True shared memory segments are not supported. "
368 "Cannot fake shared segments in SMP config.");
369 fatalf(
"Ipc::Mem::Segment: Cannot fake shared segments in SMP config (%s)\n",
void useConfig() override
POSIX shared memory segment.
off_t theReserved
the total number of reserve()d bytes
off_t theSize
shared memory segment size
void open(const bool unlinkWhenDone)
static const char * BasePath
common path of all segment names in path-based environments
static bool Enabled()
Whether shared memory support is available.
static SBuf Name(const SBuf &prefix, const char *suffix)
concatenates parts of a name to form a complete name (or its prefix)
void * theMem
pointer to mmapped shared memory segment
void * reserve(size_t chunkSize)
reserve and return the next chunk
Segment(const char *const id)
Create a shared memory segment.
void checkSupport(const char *const context)
void create(const off_t aSize)
Create a new shared memory segment. Unlinks the segment on destruction.
SBuf & append(const SBuf &S)
YesNoNone shmLocking
shared_memory_locking
void append(char const *buf, int len)
#define debugs(SECTION, LEVEL, CONTENT)
void fatalf(const char *fmt,...)
static SegmentMap Segments
std::map< String, Ipc::Mem::Segment * > SegmentMap
bool shm_portable_segment_name_is_path()
Determines whether segment names are iterpreted as full file paths.
int shm_unlink(const char *)
int shm_open(const char *, int, mode_t)
const char * xstrerr(int error)