PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
sysv_shmem.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * sysv_shmem.c
4  * Implement shared memory using SysV facilities
5  *
6  * These routines used to be a fairly thin layer on top of SysV shared
7  * memory functionality. With the addition of anonymous-shmem logic,
8  * they're a bit fatter now. We still require a SysV shmem block to
9  * exist, though, because mmap'd shmem provides no way to find out how
10  * many processes are attached, which we need for interlocking purposes.
11  *
12  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
13  * Portions Copyright (c) 1994, Regents of the University of California
14  *
15  * IDENTIFICATION
16  * src/backend/port/sysv_shmem.c
17  *
18  *-------------------------------------------------------------------------
19  */
20 #include "postgres.h"
21 
22 #include <signal.h>
23 #include <unistd.h>
24 #include <sys/file.h>
25 #include <sys/mman.h>
26 #include <sys/stat.h>
27 #ifdef HAVE_SYS_IPC_H
28 #include <sys/ipc.h>
29 #endif
30 #ifdef HAVE_SYS_SHM_H
31 #include <sys/shm.h>
32 #endif
33 
34 #include "miscadmin.h"
35 #include "portability/mem.h"
36 #include "storage/dsm.h"
37 #include "storage/fd.h"
38 #include "storage/ipc.h"
39 #include "storage/pg_shmem.h"
40 #include "utils/guc.h"
41 
42 
43 /*
44  * As of PostgreSQL 9.3, we normally allocate only a very small amount of
45  * System V shared memory, and only for the purposes of providing an
46  * interlock to protect the data directory. The real shared memory block
47  * is allocated using mmap(). This works around the problem that many
48  * systems have very low limits on the amount of System V shared memory
49  * that can be allocated. Even a limit of a few megabytes will be enough
50  * to run many copies of PostgreSQL without needing to adjust system settings.
51  *
52  * We assume that no one will attempt to run PostgreSQL 9.3 or later on
53  * systems that are ancient enough that anonymous shared memory is not
54  * supported, such as pre-2.4 versions of Linux. If that turns out to be
55  * false, we might need to add compile and/or run-time tests here and do this
56  * only if the running kernel supports it.
57  *
58  * However, we must always disable this logic in the EXEC_BACKEND case, and
59  * fall back to the old method of allocating the entire segment using System V
60  * shared memory, because there's no way to attach an anonymous mmap'd segment
61  * to a process after exec(). Since EXEC_BACKEND is intended only for
62  * developer use, this shouldn't be a big problem. Because of this, we do
63  * not worry about supporting anonymous shmem in the EXEC_BACKEND cases below.
64  */
65 #ifndef EXEC_BACKEND
66 #define USE_ANONYMOUS_SHMEM
67 #endif
68 
69 
70 typedef key_t IpcMemoryKey; /* shared memory key passed to shmget(2) */
71 typedef int IpcMemoryId; /* shared memory ID returned by shmget(2) */
72 
73 
74 unsigned long UsedShmemSegID = 0;
76 
77 #ifdef USE_ANONYMOUS_SHMEM
79 static void *AnonymousShmem = NULL;
80 #endif
81 
82 static void *InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size);
83 static void IpcMemoryDetach(int status, Datum shmaddr);
84 static void IpcMemoryDelete(int status, Datum shmId);
86  IpcMemoryId *shmid);
87 
88 
89 /*
90  * InternalIpcMemoryCreate(memKey, size)
91  *
92  * Attempt to create a new shared memory segment with the specified key.
93  * Will fail (return NULL) if such a segment already exists. If successful,
94  * attach the segment to the current process and return its attached address.
95  * On success, callbacks are registered with on_shmem_exit to detach and
96  * delete the segment when on_shmem_exit is called.
97  *
98  * If we fail with a failure code other than collision-with-existing-segment,
99  * print out an error and abort. Other types of errors are not recoverable.
100  */
101 static void *
103 {
104  IpcMemoryId shmid;
105  void *requestedAddress = NULL;
106  void *memAddress;
107 
108  /*
109  * Normally we just pass requestedAddress = NULL to shmat(), allowing the
110  * system to choose where the segment gets mapped. But in an EXEC_BACKEND
111  * build, it's possible for whatever is chosen in the postmaster to not
112  * work for backends, due to variations in address space layout. As a
113  * rather klugy workaround, allow the user to specify the address to use
114  * via setting the environment variable PG_SHMEM_ADDR. (If this were of
115  * interest for anything except debugging, we'd probably create a cleaner
116  * and better-documented way to set it, such as a GUC.)
117  */
118 #ifdef EXEC_BACKEND
119  {
120  char *pg_shmem_addr = getenv("PG_SHMEM_ADDR");
121 
122  if (pg_shmem_addr)
123  requestedAddress = (void *) strtoul(pg_shmem_addr, NULL, 0);
124  }
125 #endif
126 
127  shmid = shmget(memKey, size, IPC_CREAT | IPC_EXCL | IPCProtection);
128 
129  if (shmid < 0)
130  {
131  int shmget_errno = errno;
132 
133  /*
134  * Fail quietly if error indicates a collision with existing segment.
135  * One would expect EEXIST, given that we said IPC_EXCL, but perhaps
136  * we could get a permission violation instead? Also, EIDRM might
137  * occur if an old seg is slated for destruction but not gone yet.
138  */
139  if (shmget_errno == EEXIST || shmget_errno == EACCES
140 #ifdef EIDRM
141  || shmget_errno == EIDRM
142 #endif
143  )
144  return NULL;
145 
146  /*
147  * Some BSD-derived kernels are known to return EINVAL, not EEXIST, if
148  * there is an existing segment but it's smaller than "size" (this is
149  * a result of poorly-thought-out ordering of error tests). To
150  * distinguish between collision and invalid size in such cases, we
151  * make a second try with size = 0. These kernels do not test size
152  * against SHMMIN in the preexisting-segment case, so we will not get
153  * EINVAL a second time if there is such a segment.
154  */
155  if (shmget_errno == EINVAL)
156  {
157  shmid = shmget(memKey, 0, IPC_CREAT | IPC_EXCL | IPCProtection);
158 
159  if (shmid < 0)
160  {
161  /* As above, fail quietly if we verify a collision */
162  if (errno == EEXIST || errno == EACCES
163 #ifdef EIDRM
164  || errno == EIDRM
165 #endif
166  )
167  return NULL;
168  /* Otherwise, fall through to report the original error */
169  }
170  else
171  {
172  /*
173  * On most platforms we cannot get here because SHMMIN is
174  * greater than zero. However, if we do succeed in creating a
175  * zero-size segment, free it and then fall through to report
176  * the original error.
177  */
178  if (shmctl(shmid, IPC_RMID, NULL) < 0)
179  elog(LOG, "shmctl(%d, %d, 0) failed: %m",
180  (int) shmid, IPC_RMID);
181  }
182  }
183 
184  /*
185  * Else complain and abort.
186  *
187  * Note: at this point EINVAL should mean that either SHMMIN or SHMMAX
188  * is violated. SHMALL violation might be reported as either ENOMEM
189  * (BSDen) or ENOSPC (Linux); the Single Unix Spec fails to say which
190  * it should be. SHMMNI violation is ENOSPC, per spec. Just plain
191  * not-enough-RAM is ENOMEM.
192  */
193  errno = shmget_errno;
194  ereport(FATAL,
195  (errmsg("could not create shared memory segment: %m"),
196  errdetail("Failed system call was shmget(key=%lu, size=%zu, 0%o).",
197  (unsigned long) memKey, size,
199  (shmget_errno == EINVAL) ?
200  errhint("This error usually means that PostgreSQL's request for a shared memory "
201  "segment exceeded your kernel's SHMMAX parameter, or possibly that "
202  "it is less than "
203  "your kernel's SHMMIN parameter.\n"
204  "The PostgreSQL documentation contains more information about shared "
205  "memory configuration.") : 0,
206  (shmget_errno == ENOMEM) ?
207  errhint("This error usually means that PostgreSQL's request for a shared "
208  "memory segment exceeded your kernel's SHMALL parameter. You might need "
209  "to reconfigure the kernel with larger SHMALL.\n"
210  "The PostgreSQL documentation contains more information about shared "
211  "memory configuration.") : 0,
212  (shmget_errno == ENOSPC) ?
213  errhint("This error does *not* mean that you have run out of disk space. "
214  "It occurs either if all available shared memory IDs have been taken, "
215  "in which case you need to raise the SHMMNI parameter in your kernel, "
216  "or because the system's overall limit for shared memory has been "
217  "reached.\n"
218  "The PostgreSQL documentation contains more information about shared "
219  "memory configuration.") : 0));
220  }
221 
222  /* Register on-exit routine to delete the new segment */
224 
225  /* OK, should be able to attach to the segment */
226  memAddress = shmat(shmid, requestedAddress, PG_SHMAT_FLAGS);
227 
228  if (memAddress == (void *) -1)
229  elog(FATAL, "shmat(id=%d, addr=%p, flags=0x%x) failed: %m",
230  shmid, requestedAddress, PG_SHMAT_FLAGS);
231 
232  /* Register on-exit routine to detach new segment before deleting */
234 
235  /*
236  * Store shmem key and ID in data directory lockfile. Format to try to
237  * keep it the same length always (trailing junk in the lockfile won't
238  * hurt, but might confuse humans).
239  */
240  {
241  char line[64];
242 
243  sprintf(line, "%9lu %9lu",
244  (unsigned long) memKey, (unsigned long) shmid);
246  }
247 
248  return memAddress;
249 }
250 
251 /****************************************************************************/
252 /* IpcMemoryDetach(status, shmaddr) removes a shared memory segment */
253 /* from process' address space */
254 /* (called as an on_shmem_exit callback, hence funny argument list) */
255 /****************************************************************************/
256 static void
258 {
259  /* Detach System V shared memory block. */
260  if (shmdt(DatumGetPointer(shmaddr)) < 0)
261  elog(LOG, "shmdt(%p) failed: %m", DatumGetPointer(shmaddr));
262 }
263 
264 /****************************************************************************/
265 /* IpcMemoryDelete(status, shmId) deletes a shared memory segment */
266 /* (called as an on_shmem_exit callback, hence funny argument list) */
267 /****************************************************************************/
268 static void
270 {
271  if (shmctl(DatumGetInt32(shmId), IPC_RMID, NULL) < 0)
272  elog(LOG, "shmctl(%d, %d, 0) failed: %m",
273  DatumGetInt32(shmId), IPC_RMID);
274 }
275 
276 /*
277  * PGSharedMemoryIsInUse
278  *
279  * Is a previously-existing shmem segment still existing and in use?
280  *
281  * The point of this exercise is to detect the case where a prior postmaster
282  * crashed, but it left child backends that are still running. Therefore
283  * we only care about shmem segments that are associated with the intended
284  * DataDir. This is an important consideration since accidental matches of
285  * shmem segment IDs are reasonably common.
286  */
287 bool
288 PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
289 {
290  IpcMemoryId shmId = (IpcMemoryId) id2;
291  struct shmid_ds shmStat;
292  struct stat statbuf;
293  PGShmemHeader *hdr;
294 
295  /*
296  * We detect whether a shared memory segment is in use by seeing whether
297  * it (a) exists and (b) has any processes attached to it.
298  */
299  if (shmctl(shmId, IPC_STAT, &shmStat) < 0)
300  {
301  /*
302  * EINVAL actually has multiple possible causes documented in the
303  * shmctl man page, but we assume it must mean the segment no longer
304  * exists.
305  */
306  if (errno == EINVAL)
307  return false;
308 
309  /*
310  * EACCES implies that the segment belongs to some other userid, which
311  * means it is not a Postgres shmem segment (or at least, not one that
312  * is relevant to our data directory).
313  */
314  if (errno == EACCES)
315  return false;
316 
317  /*
318  * Some Linux kernel versions (in fact, all of them as of July 2007)
319  * sometimes return EIDRM when EINVAL is correct. The Linux kernel
320  * actually does not have any internal state that would justify
321  * returning EIDRM, so we can get away with assuming that EIDRM is
322  * equivalent to EINVAL on that platform.
323  */
324 #ifdef HAVE_LINUX_EIDRM_BUG
325  if (errno == EIDRM)
326  return false;
327 #endif
328 
329  /*
330  * Otherwise, we had better assume that the segment is in use. The
331  * only likely case is EIDRM, which implies that the segment has been
332  * IPC_RMID'd but there are still processes attached to it.
333  */
334  return true;
335  }
336 
337  /* If it has no attached processes, it's not in use */
338  if (shmStat.shm_nattch == 0)
339  return false;
340 
341  /*
342  * Try to attach to the segment and see if it matches our data directory.
343  * This avoids shmid-conflict problems on machines that are running
344  * several postmasters under the same userid.
345  */
346  if (stat(DataDir, &statbuf) < 0)
347  return true; /* if can't stat, be conservative */
348 
349  hdr = (PGShmemHeader *) shmat(shmId, NULL, PG_SHMAT_FLAGS);
350 
351  if (hdr == (PGShmemHeader *) -1)
352  return true; /* if can't attach, be conservative */
353 
354  if (hdr->magic != PGShmemMagic ||
355  hdr->device != statbuf.st_dev ||
356  hdr->inode != statbuf.st_ino)
357  {
358  /*
359  * It's either not a Postgres segment, or not one for my data
360  * directory. In either case it poses no threat.
361  */
362  shmdt((void *) hdr);
363  return false;
364  }
365 
366  /* Trouble --- looks a lot like there's still live backends */
367  shmdt((void *) hdr);
368 
369  return true;
370 }
371 
372 #ifdef USE_ANONYMOUS_SHMEM
373 
374 #ifdef MAP_HUGETLB
375 
376 /*
377  * Identify the huge page size to use.
378  *
379  * Some Linux kernel versions have a bug causing mmap() to fail on requests
380  * that are not a multiple of the hugepage size. Versions without that bug
381  * instead silently round the request up to the next hugepage multiple ---
382  * and then munmap() fails when we give it a size different from that.
383  * So we have to round our request up to a multiple of the actual hugepage
384  * size to avoid trouble.
385  *
386  * Doing the round-up ourselves also lets us make use of the extra memory,
387  * rather than just wasting it. Currently, we just increase the available
388  * space recorded in the shmem header, which will make the extra usable for
389  * purposes such as additional locktable entries. Someday, for very large
390  * hugepage sizes, we might want to think about more invasive strategies,
391  * such as increasing shared_buffers to absorb the extra space.
392  *
393  * Returns the (real or assumed) page size into *hugepagesize,
394  * and the hugepage-related mmap flags to use into *mmap_flags.
395  *
396  * Currently *mmap_flags is always just MAP_HUGETLB. Someday, on systems
397  * that support it, we might OR in additional bits to specify a particular
398  * non-default huge page size.
399  */
400 static void
401 GetHugePageSize(Size *hugepagesize, int *mmap_flags)
402 {
403  /*
404  * If we fail to find out the system's default huge page size, assume it
405  * is 2MB. This will work fine when the actual size is less. If it's
406  * more, we might get mmap() or munmap() failures due to unaligned
407  * requests; but at this writing, there are no reports of any non-Linux
408  * systems being picky about that.
409  */
410  *hugepagesize = 2 * 1024 * 1024;
411  *mmap_flags = MAP_HUGETLB;
412 
413  /*
414  * System-dependent code to find out the default huge page size.
415  *
416  * On Linux, read /proc/meminfo looking for a line like "Hugepagesize:
417  * nnnn kB". Ignore any failures, falling back to the preset default.
418  */
419 #ifdef __linux__
420  {
421  FILE *fp = AllocateFile("/proc/meminfo", "r");
422  char buf[128];
423  unsigned int sz;
424  char ch;
425 
426  if (fp)
427  {
428  while (fgets(buf, sizeof(buf), fp))
429  {
430  if (sscanf(buf, "Hugepagesize: %u %c", &sz, &ch) == 2)
431  {
432  if (ch == 'k')
433  {
434  *hugepagesize = sz * (Size) 1024;
435  break;
436  }
437  /* We could accept other units besides kB, if needed */
438  }
439  }
440  FreeFile(fp);
441  }
442  }
443 #endif /* __linux__ */
444 }
445 
446 #endif /* MAP_HUGETLB */
447 
448 /*
449  * Creates an anonymous mmap()ed shared memory segment.
450  *
451  * Pass the requested size in *size. This function will modify *size to the
452  * actual size of the allocation, if it ends up allocating a segment that is
453  * larger than requested.
454  */
455 static void *
457 {
458  Size allocsize = *size;
459  void *ptr = MAP_FAILED;
460  int mmap_errno = 0;
461 
462 #ifndef MAP_HUGETLB
463  /* PGSharedMemoryCreate should have dealt with this case */
465 #else
467  {
468  /*
469  * Round up the request size to a suitable large value.
470  */
471  Size hugepagesize;
472  int mmap_flags;
473 
474  GetHugePageSize(&hugepagesize, &mmap_flags);
475 
476  if (allocsize % hugepagesize != 0)
477  allocsize += hugepagesize - (allocsize % hugepagesize);
478 
479  ptr = mmap(NULL, allocsize, PROT_READ | PROT_WRITE,
480  PG_MMAP_FLAGS | mmap_flags, -1, 0);
481  mmap_errno = errno;
482  if (huge_pages == HUGE_PAGES_TRY && ptr == MAP_FAILED)
483  elog(DEBUG1, "mmap(%zu) with MAP_HUGETLB failed, huge pages disabled: %m",
484  allocsize);
485  }
486 #endif
487 
488  if (ptr == MAP_FAILED && huge_pages != HUGE_PAGES_ON)
489  {
490  /*
491  * Use the original size, not the rounded-up value, when falling back
492  * to non-huge pages.
493  */
494  allocsize = *size;
495  ptr = mmap(NULL, allocsize, PROT_READ | PROT_WRITE,
496  PG_MMAP_FLAGS, -1, 0);
497  mmap_errno = errno;
498  }
499 
500  if (ptr == MAP_FAILED)
501  {
502  errno = mmap_errno;
503  ereport(FATAL,
504  (errmsg("could not map anonymous shared memory: %m"),
505  (mmap_errno == ENOMEM) ?
506  errhint("This error usually means that PostgreSQL's request "
507  "for a shared memory segment exceeded available memory, "
508  "swap space, or huge pages. To reduce the request size "
509  "(currently %zu bytes), reduce PostgreSQL's shared "
510  "memory usage, perhaps by reducing shared_buffers or "
511  "max_connections.",
512  *size) : 0));
513  }
514 
515  *size = allocsize;
516  return ptr;
517 }
518 
519 /*
520  * AnonymousShmemDetach --- detach from an anonymous mmap'd block
521  * (called as an on_shmem_exit callback, hence funny argument list)
522  */
523 static void
525 {
526  /* Release anonymous shared memory block, if any. */
527  if (AnonymousShmem != NULL)
528  {
529  if (munmap(AnonymousShmem, AnonymousShmemSize) < 0)
530  elog(LOG, "munmap(%p, %zu) failed: %m",
533  }
534 }
535 
536 #endif /* USE_ANONYMOUS_SHMEM */
537 
538 /*
539  * PGSharedMemoryCreate
540  *
541  * Create a shared memory segment of the given size and initialize its
542  * standard header. Also, register an on_shmem_exit callback to release
543  * the storage.
544  *
545  * Dead Postgres segments are recycled if found, but we do not fail upon
546  * collision with non-Postgres shmem segments. The idea here is to detect and
547  * re-use keys that may have been assigned by a crashed postmaster or backend.
548  *
549  * makePrivate means to always create a new segment, rather than attach to
550  * or recycle any existing segment.
551  *
552  * The port number is passed for possible use as a key (for SysV, we use
553  * it to generate the starting shmem key). In a standalone backend,
554  * zero will be passed.
555  */
557 PGSharedMemoryCreate(Size size, bool makePrivate, int port,
558  PGShmemHeader **shim)
559 {
560  IpcMemoryKey NextShmemSegID;
561  void *memAddress;
562  PGShmemHeader *hdr;
563  IpcMemoryId shmid;
564  struct stat statbuf;
565  Size sysvsize;
566 
567  /* Complain if hugepages demanded but we can't possibly support them */
568 #if !defined(USE_ANONYMOUS_SHMEM) || !defined(MAP_HUGETLB)
569  if (huge_pages == HUGE_PAGES_ON)
570  ereport(ERROR,
571  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
572  errmsg("huge pages not supported on this platform")));
573 #endif
574 
575  /* Room for a header? */
576  Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
577 
578 #ifdef USE_ANONYMOUS_SHMEM
580  AnonymousShmemSize = size;
581 
582  /* Register on-exit routine to unmap the anonymous segment */
584 
585  /* Now we need only allocate a minimal-sized SysV shmem block. */
586  sysvsize = sizeof(PGShmemHeader);
587 #else
588  sysvsize = size;
589 #endif
590 
591  /* Make sure PGSharedMemoryAttach doesn't fail without need */
593 
594  /* Loop till we find a free IPC key */
595  NextShmemSegID = port * 1000;
596 
597  for (NextShmemSegID++;; NextShmemSegID++)
598  {
599  /* Try to create new segment */
600  memAddress = InternalIpcMemoryCreate(NextShmemSegID, sysvsize);
601  if (memAddress)
602  break; /* successful create and attach */
603 
604  /* Check shared memory and possibly remove and recreate */
605 
606  if (makePrivate) /* a standalone backend shouldn't do this */
607  continue;
608 
609  if ((memAddress = PGSharedMemoryAttach(NextShmemSegID, &shmid)) == NULL)
610  continue; /* can't attach, not one of mine */
611 
612  /*
613  * If I am not the creator and it belongs to an extant process,
614  * continue.
615  */
616  hdr = (PGShmemHeader *) memAddress;
617  if (hdr->creatorPID != getpid())
618  {
619  if (kill(hdr->creatorPID, 0) == 0 || errno != ESRCH)
620  {
621  shmdt(memAddress);
622  continue; /* segment belongs to a live process */
623  }
624  }
625 
626  /*
627  * The segment appears to be from a dead Postgres process, or from a
628  * previous cycle of life in this same process. Zap it, if possible,
629  * and any associated dynamic shared memory segments, as well. This
630  * probably shouldn't fail, but if it does, assume the segment belongs
631  * to someone else after all, and continue quietly.
632  */
633  if (hdr->dsm_control != 0)
635  shmdt(memAddress);
636  if (shmctl(shmid, IPC_RMID, NULL) < 0)
637  continue;
638 
639  /*
640  * Now try again to create the segment.
641  */
642  memAddress = InternalIpcMemoryCreate(NextShmemSegID, sysvsize);
643  if (memAddress)
644  break; /* successful create and attach */
645 
646  /*
647  * Can only get here if some other process managed to create the same
648  * shmem key before we did. Let him have that one, loop around to try
649  * next key.
650  */
651  }
652 
653  /*
654  * OK, we created a new segment. Mark it as created by this process. The
655  * order of assignments here is critical so that another Postgres process
656  * can't see the header as valid but belonging to an invalid PID!
657  */
658  hdr = (PGShmemHeader *) memAddress;
659  hdr->creatorPID = getpid();
660  hdr->magic = PGShmemMagic;
661  hdr->dsm_control = 0;
662 
663  /* Fill in the data directory ID info, too */
664  if (stat(DataDir, &statbuf) < 0)
665  ereport(FATAL,
667  errmsg("could not stat data directory \"%s\": %m",
668  DataDir)));
669  hdr->device = statbuf.st_dev;
670  hdr->inode = statbuf.st_ino;
671 
672  /*
673  * Initialize space allocation status for segment.
674  */
675  hdr->totalsize = size;
676  hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
677  *shim = hdr;
678 
679  /* Save info for possible future use */
680  UsedShmemSegAddr = memAddress;
681  UsedShmemSegID = (unsigned long) NextShmemSegID;
682 
683  /*
684  * If AnonymousShmem is NULL here, then we're not using anonymous shared
685  * memory, and should return a pointer to the System V shared memory
686  * block. Otherwise, the System V shared memory block is only a shim, and
687  * we must return a pointer to the real block.
688  */
689 #ifdef USE_ANONYMOUS_SHMEM
690  if (AnonymousShmem == NULL)
691  return hdr;
692  memcpy(AnonymousShmem, hdr, sizeof(PGShmemHeader));
693  return (PGShmemHeader *) AnonymousShmem;
694 #else
695  return hdr;
696 #endif
697 }
698 
699 #ifdef EXEC_BACKEND
700 
701 /*
702  * PGSharedMemoryReAttach
703  *
704  * This is called during startup of a postmaster child process to re-attach to
705  * an already existing shared memory segment. This is needed only in the
706  * EXEC_BACKEND case; otherwise postmaster children inherit the shared memory
707  * segment attachment via fork().
708  *
709  * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
710  * routine. The caller must have already restored them to the postmaster's
711  * values.
712  */
713 void
715 {
716  IpcMemoryId shmid;
717  void *hdr;
718  void *origUsedShmemSegAddr = UsedShmemSegAddr;
719 
722 
723 #ifdef __CYGWIN__
724  /* cygipc (currently) appears to not detach on exec. */
726  UsedShmemSegAddr = origUsedShmemSegAddr;
727 #endif
728 
729  elog(DEBUG3, "attaching to %p", UsedShmemSegAddr);
730  hdr = (void *) PGSharedMemoryAttach((IpcMemoryKey) UsedShmemSegID, &shmid);
731  if (hdr == NULL)
732  elog(FATAL, "could not reattach to shared memory (key=%d, addr=%p): %m",
734  if (hdr != origUsedShmemSegAddr)
735  elog(FATAL, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
736  hdr, origUsedShmemSegAddr);
737  dsm_set_control_handle(((PGShmemHeader *) hdr)->dsm_control);
738 
739  UsedShmemSegAddr = hdr; /* probably redundant */
740 }
741 
742 /*
743  * PGSharedMemoryNoReAttach
744  *
745  * This is called during startup of a postmaster child process when we choose
746  * *not* to re-attach to the existing shared memory segment. We must clean up
747  * to leave things in the appropriate state. This is not used in the non
748  * EXEC_BACKEND case, either.
749  *
750  * The child process startup logic might or might not call PGSharedMemoryDetach
751  * after this; make sure that it will be a no-op if called.
752  *
753  * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
754  * routine. The caller must have already restored them to the postmaster's
755  * values.
756  */
757 void
759 {
762 
763 #ifdef __CYGWIN__
764  /* cygipc (currently) appears to not detach on exec. */
766 #endif
767 
768  /* For cleanliness, reset UsedShmemSegAddr to show we're not attached. */
770  /* And the same for UsedShmemSegID. */
771  UsedShmemSegID = 0;
772 }
773 
774 #endif /* EXEC_BACKEND */
775 
776 /*
777  * PGSharedMemoryDetach
778  *
779  * Detach from the shared memory segment, if still attached. This is not
780  * intended to be called explicitly by the process that originally created the
781  * segment (it will have on_shmem_exit callback(s) registered to do that).
782  * Rather, this is for subprocesses that have inherited an attachment and want
783  * to get rid of it.
784  *
785  * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
786  * routine, also AnonymousShmem and AnonymousShmemSize.
787  */
788 void
790 {
791  if (UsedShmemSegAddr != NULL)
792  {
793  if ((shmdt(UsedShmemSegAddr) < 0)
794 #if defined(EXEC_BACKEND) && defined(__CYGWIN__)
795  /* Work-around for cygipc exec bug */
796  && shmdt(NULL) < 0
797 #endif
798  )
799  elog(LOG, "shmdt(%p) failed: %m", UsedShmemSegAddr);
801  }
802 
803 #ifdef USE_ANONYMOUS_SHMEM
804  if (AnonymousShmem != NULL)
805  {
806  if (munmap(AnonymousShmem, AnonymousShmemSize) < 0)
807  elog(LOG, "munmap(%p, %zu) failed: %m",
810  }
811 #endif
812 }
813 
814 
815 /*
816  * Attach to shared memory and make sure it has a Postgres header
817  *
818  * Returns attach address if OK, else NULL
819  */
820 static PGShmemHeader *
822 {
823  PGShmemHeader *hdr;
824 
825  if ((*shmid = shmget(key, sizeof(PGShmemHeader), 0)) < 0)
826  return NULL;
827 
828  hdr = (PGShmemHeader *) shmat(*shmid, UsedShmemSegAddr, PG_SHMAT_FLAGS);
829 
830  if (hdr == (PGShmemHeader *) -1)
831  return NULL; /* failed: must be some other app's */
832 
833  if (hdr->magic != PGShmemMagic)
834  {
835  shmdt((void *) hdr);
836  return NULL; /* segment belongs to a non-Postgres app */
837  }
838 
839  return hdr;
840 }
#define IPC_CREAT
Definition: win32.h:107
#define IPC_EXCL
Definition: win32.h:108
pid_t creatorPID
Definition: pg_shmem.h:33
#define MAP_FAILED
Definition: mem.h:45
#define DEBUG1
Definition: elog.h:25
int errhint(const char *fmt,...)
Definition: elog.c:987
static void IpcMemoryDetach(int status, Datum shmaddr)
Definition: sysv_shmem.c:257
#define DatumGetInt32(X)
Definition: postgres.h:478
#define DEBUG3
Definition: elog.h:23
void dsm_cleanup_using_control_segment(dsm_handle old_control_handle)
Definition: dsm.c:210
static PGShmemHeader * PGSharedMemoryAttach(IpcMemoryKey key, IpcMemoryId *shmid)
Definition: sysv_shmem.c:821
dsm_handle dsm_control
Definition: pg_shmem.h:36
void AddToDataDirLockFile(int target_line, const char *str)
Definition: miscinit.c:1156
#define PointerGetDatum(X)
Definition: postgres.h:562
#define IPCProtection
Definition: posix_sema.c:52
#define PG_SHMAT_FLAGS
Definition: mem.h:20
#define IPC_STAT
Definition: win32.h:111
struct PGShmemHeader PGShmemHeader
static Size AnonymousShmemSize
Definition: sysv_shmem.c:78
void PGSharedMemoryNoReAttach(void)
Definition: win32_shmem.c:315
int errcode(int sqlerrcode)
Definition: elog.c:575
#define LOG
Definition: elog.h:26
void PGSharedMemoryDetach(void)
Definition: sysv_shmem.c:789
long key_t
Definition: win32.h:253
static void * InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
Definition: sysv_shmem.c:102
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:348
static char * buf
Definition: pg_test_fsync.c:66
#define PG_MMAP_FLAGS
Definition: mem.h:41
key_t IpcMemoryKey
Definition: sysv_shmem.c:70
bool IsUnderPostmaster
Definition: globals.c:100
int errdetail(const char *fmt,...)
Definition: elog.c:873
void PGSharedMemoryReAttach(void)
Definition: win32_shmem.c:271
int errcode_for_file_access(void)
Definition: elog.c:598
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2094
void * UsedShmemSegAddr
Definition: sysv_shmem.c:75
static void AnonymousShmemDetach(int status, Datum arg)
Definition: sysv_shmem.c:524
#define ereport(elevel, rest)
Definition: elog.h:122
static void IpcMemoryDelete(int status, Datum shmId)
Definition: sysv_shmem.c:269
static int port
Definition: pg_regress.c:89
int32 magic
Definition: pg_shmem.h:31
static void * CreateAnonymousSegment(Size *size)
Definition: sysv_shmem.c:456
Size totalsize
Definition: pg_shmem.h:34
uintptr_t Datum
Definition: postgres.h:372
unsigned long UsedShmemSegID
Definition: sysv_shmem.c:74
#define IPC_RMID
Definition: win32.h:106
static void * AnonymousShmem
Definition: sysv_shmem.c:79
ino_t inode
Definition: pg_shmem.h:40
#define LOCK_FILE_LINE_SHMEM_KEY
Definition: miscadmin.h:452
static dsm_control_header * dsm_control
Definition: dsm.c:134
dev_t device
Definition: pg_shmem.h:39
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define PGShmemMagic
Definition: pg_shmem.h:32
Size freeoffset
Definition: pg_shmem.h:35
size_t Size
Definition: c.h:356
PGShmemHeader * PGSharedMemoryCreate(Size size, bool makePrivate, int port, PGShmemHeader **shim)
Definition: sysv_shmem.c:557
#define MAXALIGN(LEN)
Definition: c.h:588
int IpcMemoryId
Definition: sysv_shmem.c:71
int huge_pages
Definition: guc.c:491
#define DatumGetPointer(X)
Definition: postgres.h:555
bool PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
Definition: sysv_shmem.c:288
int FreeFile(FILE *file)
Definition: fd.c:2277
#define Int32GetDatum(X)
Definition: postgres.h:485
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * arg
char * DataDir
Definition: globals.c:59
#define EIDRM
Definition: win32.h:115
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224