Go to the documentation of this file.
44 assert(!chunkSize ||
static_cast<off_t
>(chunkSize) > 0);
64 theFD(-1), theName(GenerateName(id)), theMem(nullptr),
65 theSize(0), theReserved(0), doUnlink(false)
73 if (close(theFD) != 0) {
75 debugs(54, 5,
"close " << theName <<
": " <<
xstrerr(xerrno));
101 if (!createFresh(xerrno) && xerrno == EEXIST) {
107 debugs(54, 5,
"shm_open " << theName <<
": " <<
xstrerr(xerrno));
108 fatalf(
"Ipc::Mem::Segment::create failed to shm_open(%s): %s\n",
109 theName.termedBuf(),
xstrerr(xerrno));
112 if (ftruncate(theFD, aSize)) {
115 debugs(54, 5,
"ftruncate " << theName <<
": " <<
xstrerr(xerrno));
116 fatalf(
"Ipc::Mem::Segment::create failed to ftruncate(%s): %s\n",
117 theName.termedBuf(),
xstrerr(xerrno));
121 theSize = statSize(
"Ipc::Mem::Segment::create");
129 debugs(54, 3,
"created " << theName <<
" segment: " << theSize);
138 theFD =
shm_open(theName.termedBuf(), O_RDWR, 0);
141 debugs(54, 5,
"shm_open " << theName <<
": " <<
xstrerr(xerrno));
142 fatalf(
"Ipc::Mem::Segment::open failed to shm_open(%s): %s\n",
143 theName.termedBuf(),
xstrerr(xerrno));
146 theSize = statSize(
"Ipc::Mem::Segment::open");
147 doUnlink = unlinkWhenDone;
149 debugs(54, 3,
"opened " << theName <<
" segment: " << theSize);
157 Ipc::Mem::Segment::createFresh(
int &xerrno)
159 theFD =
shm_open(theName.termedBuf(),
160 O_EXCL | O_CREAT | O_RDWR,
168 Ipc::Mem::Segment::attach()
175 assert(theSize ==
static_cast<off_t
>(
static_cast<size_t>(theSize)));
178 mmap(
nullptr, theSize, PROT_READ | PROT_WRITE, MAP_SHARED, theFD, 0);
179 if (p == MAP_FAILED) {
181 debugs(54, 5,
"mmap " << theName <<
": " <<
xstrerr(xerrno));
182 fatalf(
"Ipc::Mem::Segment::attach failed to mmap(%s): %s\n",
183 theName.termedBuf(),
xstrerr(xerrno));
192 Ipc::Mem::Segment::detach()
197 if (munmap(theMem, theSize)) {
199 debugs(54, 5,
"munmap " << theName <<
": " <<
xstrerr(xerrno));
200 fatalf(
"Ipc::Mem::Segment::detach failed to munmap(%s): %s\n",
201 theName.termedBuf(),
xstrerr(xerrno));
209 Ipc::Mem::Segment::lock()
212 debugs(54, 5,
"mlock(2)-ing disabled");
216 #if defined(_POSIX_MEMLOCK_RANGE)
217 debugs(54, 7,
"mlock(" << theName <<
',' << theSize <<
") starts");
218 if (mlock(theMem, theSize) != 0) {
219 const int savedError = errno;
220 fatalf(
"shared_memory_locking on but failed to mlock(%s, %" PRId64 "): %s\n",
221 theName.termedBuf(),
static_cast<int64_t
>(theSize),
xstrerr(savedError));
224 debugs(54, 7,
"mlock(" << theName <<
',' << theSize <<
") OK");
226 debugs(54, 5,
"insufficient mlock(2) support");
228 static bool warnedOnce =
false;
231 "honoring `shared_memory_locking on`. " <<
232 "If you lack RAM, kernel will kill Squid later.");
240 Ipc::Mem::Segment::unlink()
244 debugs(54, 5,
"shm_unlink(" << theName <<
"): " <<
xstrerr(xerrno));
246 debugs(54, 3,
"unlinked " << theName <<
" segment");
251 Ipc::Mem::Segment::statSize(
const char *context)
const
256 memset(&s, 0,
sizeof(s));
258 if (fstat(theFD, &s) != 0) {
260 debugs(54, 5, context <<
" fstat " << theName <<
": " <<
xstrerr(xerrno));
261 fatalf(
"Ipc::Mem::Segment::statSize: %s failed to fstat(%s): %s\n",
262 context, theName.termedBuf(),
xstrerr(xerrno));
271 Ipc::Mem::Segment::GenerateName(
const char *
id)
273 assert(BasePath && *BasePath);
278 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",
const char * xstrerr(int error)
bool shm_portable_segment_name_is_path()
Determines whether segment names are iterpreted as full file paths.
Segment(const char *const id)
Create a shared memory segment.
int shm_unlink(const char *)
void * theMem
pointer to mmapped shared memory segment
void * reserve(size_t chunkSize)
reserve and return the next chunk
static const char * BasePath
common path of all segment names in path-based environments
void append(char const *buf, int len)
off_t theSize
shared memory segment size
SBuf NamePrefix(const char *head, const char *tail=nullptr)
void fatalf(const char *fmt,...)
void useConfig() override
POSIX shared memory segment.
void checkSupport(const char *const context)
SBuf & append(const SBuf &S)
static SBuf Name(const SBuf &prefix, const char *suffix)
concatenates parts of a name to form a complete name (or its prefix)
static bool Enabled()
Whether shared memory support is available.
off_t theReserved
the total number of reserve()d bytes
YesNoNone shmLocking
shared_memory_locking
void open(const bool unlinkWhenDone)
void create(const off_t aSize)
Create a new shared memory segment. Unlinks the segment on destruction.
std::map< String, Ipc::Mem::Segment * > SegmentMap
static SegmentMap Segments
#define debugs(SECTION, LEVEL, CONTENT)
int shm_open(const char *, int, mode_t)