このページを編集する際は、編集に関する方針に従ってください。
PGShmemHeader * PGSharedMemoryCreate(Size size, bool makePrivate, int port) {
IpcMemoryKey NextShmemSegID;
void *memAddress; PGShmemHeader *hdr;
IpcMemoryId shmid;
#ifndef WIN32 struct stat statbuf;
#endif
/* Room for a header? */ Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
/* Make sure PGSharedMemoryAttach doesn't fail without need */ UsedShmemSegAddr = NULL;
/* Loop till we find a free IPC key */ NextShmemSegID = port * 1000;
for (NextShmemSegID++;; NextShmemSegID++) { /* Try to create new segment */ memAddress = InternalIpcMemoryCreate(NextShmemSegID, size);
if (memAddress) break; /* successful create and attach */
/* Check shared memory and possibly remove and recreate */
if (makePrivate) /* a standalone backend shouldn't do this */ continue;
if ((memAddress = PGSharedMemoryAttach(NextShmemSegID, &shmid)) == NULL) continue; /* can't attach, not one of mine */
/* * If I am not the creator and it belongs to an extant process, * continue. */ hdr = (PGShmemHeader *) memAddress; if (hdr->creatorPID != getpid()) { if (kill(hdr->creatorPID, 0) == 0 || errno != ESRCH) { shmdt(memAddress); continue; /* segment belongs to a live process */ } }
/* * The segment appears to be from a dead Postgres process, or from a * previous cycle of life in this same process. Zap it, if possible. * This probably shouldn't fail, but if it does, assume the segment * belongs to someone else after all, and continue quietly. */ shmdt(memAddress); if (shmctl(shmid, IPC_RMID, NULL) < 0) continue;
/* * Now try again to create the segment. */ memAddress = InternalIpcMemoryCreate(NextShmemSegID, size); if (memAddress) break; /* successful create and attach */
/* * Can only get here if some other process managed to create the same * shmem key before we did. Let him have that one, loop around to try * next key. */ }
/* * OK, we created a new segment. Mark it as created by this process. The * order of assignments here is critical so that another Postgres process * can't see the header as valid but belonging to an invalid PID! */ hdr = (PGShmemHeader *) memAddress; hdr->creatorPID = getpid(); hdr->magic = PGShmemMagic;
#ifndef WIN32 /* Fill in the data directory ID info, too */ if (stat(DataDir, &statbuf) < 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not stat data directory \"%s\": %m", DataDir))); hdr->device = statbuf.st_dev; hdr->inode = statbuf.st_ino; #endif
/* * Initialize space allocation status for segment. */ hdr->totalsize = size; hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
/* Save info for possible future use */ UsedShmemSegAddr = memAddress; UsedShmemSegID = (unsigned long) NextShmemSegID;
return hdr; }
/* * PGSharedMemoryCreate * * Create a shared memory segment of the given size and initialize its * standard header. Also, register an on_shmem_exit callback to release * the storage. * * Dead Postgres segments are recycled if found, but we do not fail upon * collision with non-Postgres shmem segments. The idea here is to detect and * re-use keys that may have been assigned by a crashed postmaster or backend. * * makePrivate means to always create a new segment, rather than attach to * or recycle any existing segment. * * The port number is passed for possible use as a key (for SysV, we use * it to generate the starting shmem key). In a standalone backend, * zero will be passed. */
更新日 | 更新者 | 更新内容 |