PostgreSQL Source Code  git master
launch_backend.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * launch_backend.c
4  * Functions for launching backends and other postmaster child
5  * processes.
6  *
7  * On Unix systems, a new child process is launched with fork(). It inherits
8  * all the global variables and data structures that had been initialized in
9  * the postmaster. After forking, the child process closes the file
10  * descriptors that are not needed in the child process, and sets up the
11  * mechanism to detect death of the parent postmaster process, etc. After
12  * that, it calls the right Main function depending on the kind of child
13  * process.
14  *
15  * In EXEC_BACKEND mode, which is used on Windows but can be enabled on other
16  * platforms for testing, the child process is launched by fork() + exec() (or
17  * CreateProcess() on Windows). It does not inherit the state from the
18  * postmaster, so it needs to re-attach to the shared memory, re-initialize
19  * global variables, reload the config file etc. to get the process to the
20  * same state as after fork() on a Unix system.
21  *
22  *
23  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
24  * Portions Copyright (c) 1994, Regents of the University of California
25  *
26  * IDENTIFICATION
27  * src/backend/postmaster/launch_backend.c
28  *
29  *-------------------------------------------------------------------------
30  */
31 
32 #include "postgres.h"
33 
34 #include <unistd.h>
35 
36 #include "libpq/libpq-be.h"
37 #include "miscadmin.h"
38 #include "postmaster/autovacuum.h"
40 #include "postmaster/bgwriter.h"
42 #include "postmaster/pgarch.h"
43 #include "postmaster/postmaster.h"
44 #include "postmaster/startup.h"
45 #include "postmaster/syslogger.h"
47 #include "postmaster/walwriter.h"
48 #include "replication/slotsync.h"
50 #include "storage/dsm.h"
51 #include "storage/pg_shmem.h"
52 #include "tcop/backend_startup.h"
53 #include "utils/memutils.h"
54 
55 #ifdef EXEC_BACKEND
56 #include "nodes/queryjumble.h"
57 #include "storage/pg_shmem.h"
58 #include "storage/spin.h"
59 #endif
60 
61 
62 #ifdef EXEC_BACKEND
63 
64 #include "common/file_utils.h"
65 #include "storage/fd.h"
66 #include "storage/lwlock.h"
67 #include "storage/pmsignal.h"
68 #include "storage/proc.h"
69 #include "storage/procsignal.h"
70 #include "tcop/tcopprot.h"
71 #include "utils/injection_point.h"
72 
73 /* Type for a socket that can be inherited to a client process */
74 #ifdef WIN32
75 typedef struct
76 {
77  SOCKET origsocket; /* Original socket value, or PGINVALID_SOCKET
78  * if not a socket */
79  WSAPROTOCOL_INFO wsainfo;
80 } InheritableSocket;
81 #else
82 typedef int InheritableSocket;
83 #endif
84 
85 /*
86  * Structure contains all variables passed to exec:ed backends
87  */
88 typedef struct
89 {
90  char DataDir[MAXPGPATH];
91 #ifndef WIN32
92  unsigned long UsedShmemSegID;
93 #else
95  HANDLE UsedShmemSegID;
96 #endif
97  void *UsedShmemSegAddr;
98  slock_t *ShmemLock;
99 #ifdef USE_INJECTION_POINTS
100  struct InjectionPointsCtl *ActiveInjectionPoints;
101 #endif
105  slock_t *ProcStructLock;
109  volatile PMSignalData *PMSignalState;
111  pid_t PostmasterPid;
115  bool redirection_done;
116  bool IsBinaryUpgrade;
117  bool query_id_enabled;
118  int max_safe_fds;
119  int MaxBackends;
120  int num_pmchild_slots;
121 #ifdef WIN32
122  HANDLE PostmasterHandle;
123  HANDLE initial_signal_pipe;
124  HANDLE syslogPipe[2];
125 #else
126  int postmaster_alive_fds[2];
127  int syslogPipe[2];
128 #endif
129  char my_exec_path[MAXPGPATH];
130  char pkglib_path[MAXPGPATH];
131 
132  int MyPMChildSlot;
133 
134  /*
135  * These are only used by backend processes, but are here because passing
136  * a socket needs some special handling on Windows. 'client_sock' is an
137  * explicit argument to postmaster_child_launch, but is stored in
138  * MyClientSocket in the child process.
139  */
140  ClientSocket client_sock;
141  InheritableSocket inh_sock;
142 
143  /*
144  * Extra startup data, content depends on the child process.
145  */
146  size_t startup_data_len;
147  char startup_data[FLEXIBLE_ARRAY_MEMBER];
148 } BackendParameters;
149 
150 #define SizeOfBackendParameters(startup_data_len) (offsetof(BackendParameters, startup_data) + startup_data_len)
151 
152 static void read_backend_variables(char *id, char **startup_data, size_t *startup_data_len);
153 static void restore_backend_variables(BackendParameters *param);
154 
155 static bool save_backend_variables(BackendParameters *param, int child_slot,
156  ClientSocket *client_sock,
157 #ifdef WIN32
158  HANDLE childProcess, pid_t childPid,
159 #endif
160  char *startup_data, size_t startup_data_len);
161 
162 static pid_t internal_forkexec(const char *child_kind, int child_slot,
163  char *startup_data, size_t startup_data_len,
164  ClientSocket *client_sock);
165 
166 #endif /* EXEC_BACKEND */
167 
168 /*
169  * Information needed to launch different kinds of child processes.
170  */
171 typedef struct
172 {
173  const char *name;
174  void (*main_fn) (char *startup_data, size_t startup_data_len) pg_attribute_noreturn();
177 
179  [B_INVALID] = {"invalid", NULL, false},
180 
181  [B_BACKEND] = {"backend", BackendMain, true},
182  [B_DEAD_END_BACKEND] = {"dead-end backend", BackendMain, true},
183  [B_AUTOVAC_LAUNCHER] = {"autovacuum launcher", AutoVacLauncherMain, true},
184  [B_AUTOVAC_WORKER] = {"autovacuum worker", AutoVacWorkerMain, true},
185  [B_BG_WORKER] = {"bgworker", BackgroundWorkerMain, true},
186 
187  /*
188  * WAL senders start their life as regular backend processes, and change
189  * their type after authenticating the client for replication. We list it
190  * here for PostmasterChildName() but cannot launch them directly.
191  */
192  [B_WAL_SENDER] = {"wal sender", NULL, true},
193  [B_SLOTSYNC_WORKER] = {"slot sync worker", ReplSlotSyncWorkerMain, true},
194 
195  [B_STANDALONE_BACKEND] = {"standalone backend", NULL, false},
196 
197  [B_ARCHIVER] = {"archiver", PgArchiverMain, true},
198  [B_BG_WRITER] = {"bgwriter", BackgroundWriterMain, true},
199  [B_CHECKPOINTER] = {"checkpointer", CheckpointerMain, true},
200  [B_STARTUP] = {"startup", StartupProcessMain, true},
201  [B_WAL_RECEIVER] = {"wal_receiver", WalReceiverMain, true},
202  [B_WAL_SUMMARIZER] = {"wal_summarizer", WalSummarizerMain, true},
203  [B_WAL_WRITER] = {"wal_writer", WalWriterMain, true},
204 
205  [B_LOGGER] = {"syslogger", SysLoggerMain, false},
206 };
207 
208 const char *
210 {
211  return child_process_kinds[child_type].name;
212 }
213 
214 /*
215  * Start a new postmaster child process.
216  *
217  * The child process will be restored to roughly the same state whether
218  * EXEC_BACKEND is used or not: it will be attached to shared memory if
219  * appropriate, and fds and other resources that we've inherited from
220  * postmaster that are not needed in a child process have been closed.
221  *
222  * 'child_slot' is the PMChildFlags array index reserved for the child
223  * process. 'startup_data' is an optional contiguous chunk of data that is
224  * passed to the child process.
225  */
226 pid_t
227 postmaster_child_launch(BackendType child_type, int child_slot,
228  char *startup_data, size_t startup_data_len,
229  ClientSocket *client_sock)
230 {
231  pid_t pid;
232 
234 
235 #ifdef EXEC_BACKEND
236  pid = internal_forkexec(child_process_kinds[child_type].name, child_slot,
237  startup_data, startup_data_len, client_sock);
238  /* the child process will arrive in SubPostmasterMain */
239 #else /* !EXEC_BACKEND */
240  pid = fork_process();
241  if (pid == 0) /* child */
242  {
243  /* Close the postmaster's sockets */
244  ClosePostmasterPorts(child_type == B_LOGGER);
245 
246  /* Detangle from postmaster */
248 
249  /* Detach shared memory if not needed. */
250  if (!child_process_kinds[child_type].shmem_attach)
251  {
252  dsm_detach_all();
254  }
255 
256  /*
257  * Enter the Main function with TopMemoryContext. The startup data is
258  * allocated in PostmasterContext, so we cannot release it here yet.
259  * The Main function will do it after it's done handling the startup
260  * data.
261  */
263 
264  MyPMChildSlot = child_slot;
265  if (client_sock)
266  {
268  memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
269  }
270 
271  /*
272  * Run the appropriate Main function
273  */
274  child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
275  pg_unreachable(); /* main_fn never returns */
276  }
277 #endif /* EXEC_BACKEND */
278  return pid;
279 }
280 
281 #ifdef EXEC_BACKEND
282 #ifndef WIN32
283 
284 /*
285  * internal_forkexec non-win32 implementation
286  *
287  * - writes out backend variables to the parameter file
288  * - fork():s, and then exec():s the child process
289  */
290 static pid_t
291 internal_forkexec(const char *child_kind, int child_slot,
292  char *startup_data, size_t startup_data_len, ClientSocket *client_sock)
293 {
294  static unsigned long tmpBackendFileNum = 0;
295  pid_t pid;
296  char tmpfilename[MAXPGPATH];
297  size_t paramsz;
298  BackendParameters *param;
299  FILE *fp;
300  char *argv[4];
301  char forkav[MAXPGPATH];
302 
303  /*
304  * Use palloc0 to make sure padding bytes are initialized, to prevent
305  * Valgrind from complaining about writing uninitialized bytes to the
306  * file. This isn't performance critical, and the win32 implementation
307  * initializes the padding bytes to zeros, so do it even when not using
308  * Valgrind.
309  */
310  paramsz = SizeOfBackendParameters(startup_data_len);
311  param = palloc0(paramsz);
312  if (!save_backend_variables(param, child_slot, client_sock, startup_data, startup_data_len))
313  {
314  pfree(param);
315  return -1; /* log made by save_backend_variables */
316  }
317 
318  /* Calculate name for temp file */
319  snprintf(tmpfilename, MAXPGPATH, "%s/%s.backend_var.%d.%lu",
321  MyProcPid, ++tmpBackendFileNum);
322 
323  /* Open file */
324  fp = AllocateFile(tmpfilename, PG_BINARY_W);
325  if (!fp)
326  {
327  /*
328  * As in OpenTemporaryFileInTablespace, try to make the temp-file
329  * directory, ignoring errors.
330  */
332 
333  fp = AllocateFile(tmpfilename, PG_BINARY_W);
334  if (!fp)
335  {
336  ereport(LOG,
338  errmsg("could not create file \"%s\": %m",
339  tmpfilename)));
340  pfree(param);
341  return -1;
342  }
343  }
344 
345  if (fwrite(param, paramsz, 1, fp) != 1)
346  {
347  ereport(LOG,
349  errmsg("could not write to file \"%s\": %m", tmpfilename)));
350  FreeFile(fp);
351  pfree(param);
352  return -1;
353  }
354  pfree(param);
355 
356  /* Release file */
357  if (FreeFile(fp))
358  {
359  ereport(LOG,
361  errmsg("could not write to file \"%s\": %m", tmpfilename)));
362  return -1;
363  }
364 
365  /* set up argv properly */
366  argv[0] = "postgres";
367  snprintf(forkav, MAXPGPATH, "--forkchild=%s", child_kind);
368  argv[1] = forkav;
369  /* Insert temp file name after --forkchild argument */
370  argv[2] = tmpfilename;
371  argv[3] = NULL;
372 
373  /* Fire off execv in child */
374  if ((pid = fork_process()) == 0)
375  {
376  if (execv(postgres_exec_path, argv) < 0)
377  {
378  ereport(LOG,
379  (errmsg("could not execute server process \"%s\": %m",
380  postgres_exec_path)));
381  /* We're already in the child process here, can't return */
382  exit(1);
383  }
384  }
385 
386  return pid; /* Parent returns pid, or -1 on fork failure */
387 }
388 #else /* WIN32 */
389 
390 /*
391  * internal_forkexec win32 implementation
392  *
393  * - starts backend using CreateProcess(), in suspended state
394  * - writes out backend variables to the parameter file
395  * - during this, duplicates handles and sockets required for
396  * inheritance into the new process
397  * - resumes execution of the new process once the backend parameter
398  * file is complete.
399  */
400 static pid_t
401 internal_forkexec(const char *child_kind, int child_slot,
402  char *startup_data, size_t startup_data_len, ClientSocket *client_sock)
403 {
404  int retry_count = 0;
405  STARTUPINFO si;
406  PROCESS_INFORMATION pi;
407  char cmdLine[MAXPGPATH * 2];
408  HANDLE paramHandle;
409  BackendParameters *param;
410  SECURITY_ATTRIBUTES sa;
411  size_t paramsz;
412  char paramHandleStr[32];
413  int l;
414 
415  paramsz = SizeOfBackendParameters(startup_data_len);
416 
417  /* Resume here if we need to retry */
418 retry:
419 
420  /* Set up shared memory for parameter passing */
421  ZeroMemory(&sa, sizeof(sa));
422  sa.nLength = sizeof(sa);
423  sa.bInheritHandle = TRUE;
424  paramHandle = CreateFileMapping(INVALID_HANDLE_VALUE,
425  &sa,
426  PAGE_READWRITE,
427  0,
428  paramsz,
429  NULL);
430  if (paramHandle == INVALID_HANDLE_VALUE)
431  {
432  ereport(LOG,
433  (errmsg("could not create backend parameter file mapping: error code %lu",
434  GetLastError())));
435  return -1;
436  }
437  param = MapViewOfFile(paramHandle, FILE_MAP_WRITE, 0, 0, paramsz);
438  if (!param)
439  {
440  ereport(LOG,
441  (errmsg("could not map backend parameter memory: error code %lu",
442  GetLastError())));
443  CloseHandle(paramHandle);
444  return -1;
445  }
446 
447  /* Format the cmd line */
448 #ifdef _WIN64
449  sprintf(paramHandleStr, "%llu", (LONG_PTR) paramHandle);
450 #else
451  sprintf(paramHandleStr, "%lu", (DWORD) paramHandle);
452 #endif
453  l = snprintf(cmdLine, sizeof(cmdLine) - 1, "\"%s\" --forkchild=\"%s\" %s",
454  postgres_exec_path, child_kind, paramHandleStr);
455  if (l >= sizeof(cmdLine))
456  {
457  ereport(LOG,
458  (errmsg("subprocess command line too long")));
459  UnmapViewOfFile(param);
460  CloseHandle(paramHandle);
461  return -1;
462  }
463 
464  memset(&pi, 0, sizeof(pi));
465  memset(&si, 0, sizeof(si));
466  si.cb = sizeof(si);
467 
468  /*
469  * Create the subprocess in a suspended state. This will be resumed later,
470  * once we have written out the parameter file.
471  */
472  if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, CREATE_SUSPENDED,
473  NULL, NULL, &si, &pi))
474  {
475  ereport(LOG,
476  (errmsg("CreateProcess() call failed: %m (error code %lu)",
477  GetLastError())));
478  UnmapViewOfFile(param);
479  CloseHandle(paramHandle);
480  return -1;
481  }
482 
483  if (!save_backend_variables(param, child_slot, client_sock,
484  pi.hProcess, pi.dwProcessId,
485  startup_data, startup_data_len))
486  {
487  /*
488  * log made by save_backend_variables, but we have to clean up the
489  * mess with the half-started process
490  */
491  if (!TerminateProcess(pi.hProcess, 255))
492  ereport(LOG,
493  (errmsg_internal("could not terminate unstarted process: error code %lu",
494  GetLastError())));
495  CloseHandle(pi.hProcess);
496  CloseHandle(pi.hThread);
497  UnmapViewOfFile(param);
498  CloseHandle(paramHandle);
499  return -1; /* log made by save_backend_variables */
500  }
501 
502  /* Drop the parameter shared memory that is now inherited to the backend */
503  if (!UnmapViewOfFile(param))
504  ereport(LOG,
505  (errmsg("could not unmap view of backend parameter file: error code %lu",
506  GetLastError())));
507  if (!CloseHandle(paramHandle))
508  ereport(LOG,
509  (errmsg("could not close handle to backend parameter file: error code %lu",
510  GetLastError())));
511 
512  /*
513  * Reserve the memory region used by our main shared memory segment before
514  * we resume the child process. Normally this should succeed, but if ASLR
515  * is active then it might sometimes fail due to the stack or heap having
516  * gotten mapped into that range. In that case, just terminate the
517  * process and retry.
518  */
519  if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
520  {
521  /* pgwin32_ReserveSharedMemoryRegion already made a log entry */
522  if (!TerminateProcess(pi.hProcess, 255))
523  ereport(LOG,
524  (errmsg_internal("could not terminate process that failed to reserve memory: error code %lu",
525  GetLastError())));
526  CloseHandle(pi.hProcess);
527  CloseHandle(pi.hThread);
528  if (++retry_count < 100)
529  goto retry;
530  ereport(LOG,
531  (errmsg("giving up after too many tries to reserve shared memory"),
532  errhint("This might be caused by ASLR or antivirus software.")));
533  return -1;
534  }
535 
536  /*
537  * Now that the backend variables are written out, we start the child
538  * thread so it can start initializing while we set up the rest of the
539  * parent state.
540  */
541  if (ResumeThread(pi.hThread) == -1)
542  {
543  if (!TerminateProcess(pi.hProcess, 255))
544  {
545  ereport(LOG,
546  (errmsg_internal("could not terminate unstartable process: error code %lu",
547  GetLastError())));
548  CloseHandle(pi.hProcess);
549  CloseHandle(pi.hThread);
550  return -1;
551  }
552  CloseHandle(pi.hProcess);
553  CloseHandle(pi.hThread);
554  ereport(LOG,
555  (errmsg_internal("could not resume thread of unstarted process: error code %lu",
556  GetLastError())));
557  return -1;
558  }
559 
560  /* Set up notification when the child process dies */
561  pgwin32_register_deadchild_callback(pi.hProcess, pi.dwProcessId);
562 
563  /* Don't close pi.hProcess, it's owned by the deadchild callback now */
564 
565  CloseHandle(pi.hThread);
566 
567  return pi.dwProcessId;
568 }
569 #endif /* WIN32 */
570 
571 /*
572  * SubPostmasterMain -- Get the fork/exec'd process into a state equivalent
573  * to what it would be if we'd simply forked on Unix, and then
574  * dispatch to the appropriate place.
575  *
576  * The first two command line arguments are expected to be "--forkchild=<name>",
577  * where <name> indicates which postmaster child we are to become, and
578  * the name of a variables file that we can read to load data that would
579  * have been inherited by fork() on Unix.
580  */
581 void
582 SubPostmasterMain(int argc, char *argv[])
583 {
584  char *startup_data;
585  size_t startup_data_len;
586  char *child_kind;
587  BackendType child_type;
588  bool found = false;
589 
590  /* In EXEC_BACKEND case we will not have inherited these settings */
593 
594  /* Setup essential subsystems (to ensure elog() behaves sanely) */
596 
597  /* Check we got appropriate args */
598  if (argc != 3)
599  elog(FATAL, "invalid subpostmaster invocation");
600 
601  /* Find the entry in child_process_kinds */
602  if (strncmp(argv[1], "--forkchild=", 12) != 0)
603  elog(FATAL, "invalid subpostmaster invocation (--forkchild argument missing)");
604  child_kind = argv[1] + 12;
605  found = false;
606  for (int idx = 0; idx < lengthof(child_process_kinds); idx++)
607  {
608  if (strcmp(child_process_kinds[idx].name, child_kind) == 0)
609  {
610  child_type = (BackendType) idx;
611  found = true;
612  break;
613  }
614  }
615  if (!found)
616  elog(ERROR, "unknown child kind %s", child_kind);
617 
618  /* Read in the variables file */
619  read_backend_variables(argv[2], &startup_data, &startup_data_len);
620 
621  /* Close the postmaster's sockets (as soon as we know them) */
622  ClosePostmasterPorts(child_type == B_LOGGER);
623 
624  /* Setup as postmaster child */
626 
627  /*
628  * If appropriate, physically re-attach to shared memory segment. We want
629  * to do this before going any further to ensure that we can attach at the
630  * same address the postmaster used. On the other hand, if we choose not
631  * to re-attach, we may have other cleanup to do.
632  *
633  * If testing EXEC_BACKEND on Linux, you should run this as root before
634  * starting the postmaster:
635  *
636  * sysctl -w kernel.randomize_va_space=0
637  *
638  * This prevents using randomized stack and code addresses that cause the
639  * child process's memory map to be different from the parent's, making it
640  * sometimes impossible to attach to shared memory at the desired address.
641  * Return the setting to its old value (usually '1' or '2') when finished.
642  */
643  if (child_process_kinds[child_type].shmem_attach)
645  else
647 
648  /* Read in remaining GUC variables */
649  read_nondefault_variables();
650 
651  /*
652  * Check that the data directory looks valid, which will also check the
653  * privileges on the data directory and update our umask and file/group
654  * variables for creating files later. Note: this should really be done
655  * before we create any files or directories.
656  */
657  checkDataDir();
658 
659  /*
660  * (re-)read control file, as it contains config. The postmaster will
661  * already have read this, but this process doesn't know about that.
662  */
664 
665  /*
666  * Reload any libraries that were preloaded by the postmaster. Since we
667  * exec'd this process, those libraries didn't come along with us; but we
668  * should load them into all child processes to be consistent with the
669  * non-EXEC_BACKEND behavior.
670  */
672 
673  /* Restore basic shared memory pointers */
674  if (UsedShmemSegAddr != NULL)
676 
677  /*
678  * Run the appropriate Main function
679  */
680  child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
681  pg_unreachable(); /* main_fn never returns */
682 }
683 
684 #ifndef WIN32
685 #define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
686 #define read_inheritable_socket(dest, src) (*(dest) = *(src))
687 #else
688 static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
689 static bool write_inheritable_socket(InheritableSocket *dest, SOCKET src,
690  pid_t childPid);
691 static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
692 #endif
693 
694 
695 /* Save critical backend variables into the BackendParameters struct */
696 static bool
697 save_backend_variables(BackendParameters *param,
698  int child_slot, ClientSocket *client_sock,
699 #ifdef WIN32
700  HANDLE childProcess, pid_t childPid,
701 #endif
702  char *startup_data, size_t startup_data_len)
703 {
704  if (client_sock)
705  memcpy(&param->client_sock, client_sock, sizeof(ClientSocket));
706  else
707  memset(&param->client_sock, 0, sizeof(ClientSocket));
708  if (!write_inheritable_socket(&param->inh_sock,
709  client_sock ? client_sock->sock : PGINVALID_SOCKET,
710  childPid))
711  return false;
712 
713  strlcpy(param->DataDir, DataDir, MAXPGPATH);
714 
715  param->MyPMChildSlot = child_slot;
716 
717 #ifdef WIN32
718  param->ShmemProtectiveRegion = ShmemProtectiveRegion;
719 #endif
720  param->UsedShmemSegID = UsedShmemSegID;
721  param->UsedShmemSegAddr = UsedShmemSegAddr;
722 
723  param->ShmemLock = ShmemLock;
724 
725 #ifdef USE_INJECTION_POINTS
726  param->ActiveInjectionPoints = ActiveInjectionPoints;
727 #endif
728 
729  param->NamedLWLockTrancheRequests = NamedLWLockTrancheRequests;
730  param->NamedLWLockTrancheArray = NamedLWLockTrancheArray;
731  param->MainLWLockArray = MainLWLockArray;
732  param->ProcStructLock = ProcStructLock;
733  param->ProcGlobal = ProcGlobal;
734  param->AuxiliaryProcs = AuxiliaryProcs;
735  param->PreparedXactProcs = PreparedXactProcs;
736  param->PMSignalState = PMSignalState;
737  param->ProcSignal = ProcSignal;
738 
739  param->PostmasterPid = PostmasterPid;
740  param->PgStartTime = PgStartTime;
741  param->PgReloadTime = PgReloadTime;
742  param->first_syslogger_file_time = first_syslogger_file_time;
743 
744  param->redirection_done = redirection_done;
745  param->IsBinaryUpgrade = IsBinaryUpgrade;
746  param->query_id_enabled = query_id_enabled;
747  param->max_safe_fds = max_safe_fds;
748 
749  param->MaxBackends = MaxBackends;
750  param->num_pmchild_slots = num_pmchild_slots;
751 
752 #ifdef WIN32
753  param->PostmasterHandle = PostmasterHandle;
754  if (!write_duplicated_handle(&param->initial_signal_pipe,
756  childProcess))
757  return false;
758 #else
759  memcpy(&param->postmaster_alive_fds, &postmaster_alive_fds,
760  sizeof(postmaster_alive_fds));
761 #endif
762 
763  memcpy(&param->syslogPipe, &syslogPipe, sizeof(syslogPipe));
764 
765  strlcpy(param->my_exec_path, my_exec_path, MAXPGPATH);
766 
767  strlcpy(param->pkglib_path, pkglib_path, MAXPGPATH);
768 
769  param->startup_data_len = startup_data_len;
770  if (startup_data_len > 0)
771  memcpy(param->startup_data, startup_data, startup_data_len);
772 
773  return true;
774 }
775 
776 #ifdef WIN32
777 /*
778  * Duplicate a handle for usage in a child process, and write the child
779  * process instance of the handle to the parameter file.
780  */
781 static bool
782 write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE childProcess)
783 {
784  HANDLE hChild = INVALID_HANDLE_VALUE;
785 
786  if (!DuplicateHandle(GetCurrentProcess(),
787  src,
788  childProcess,
789  &hChild,
790  0,
791  TRUE,
792  DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
793  {
794  ereport(LOG,
795  (errmsg_internal("could not duplicate handle to be written to backend parameter file: error code %lu",
796  GetLastError())));
797  return false;
798  }
799 
800  *dest = hChild;
801  return true;
802 }
803 
804 /*
805  * Duplicate a socket for usage in a child process, and write the resulting
806  * structure to the parameter file.
807  * This is required because a number of LSPs (Layered Service Providers) very
808  * common on Windows (antivirus, firewalls, download managers etc) break
809  * straight socket inheritance.
810  */
811 static bool
812 write_inheritable_socket(InheritableSocket *dest, SOCKET src, pid_t childpid)
813 {
814  dest->origsocket = src;
815  if (src != 0 && src != PGINVALID_SOCKET)
816  {
817  /* Actual socket */
818  if (WSADuplicateSocket(src, childpid, &dest->wsainfo) != 0)
819  {
820  ereport(LOG,
821  (errmsg("could not duplicate socket %d for use in backend: error code %d",
822  (int) src, WSAGetLastError())));
823  return false;
824  }
825  }
826  return true;
827 }
828 
829 /*
830  * Read a duplicate socket structure back, and get the socket descriptor.
831  */
832 static void
833 read_inheritable_socket(SOCKET *dest, InheritableSocket *src)
834 {
835  SOCKET s;
836 
837  if (src->origsocket == PGINVALID_SOCKET || src->origsocket == 0)
838  {
839  /* Not a real socket! */
840  *dest = src->origsocket;
841  }
842  else
843  {
844  /* Actual socket, so create from structure */
845  s = WSASocket(FROM_PROTOCOL_INFO,
846  FROM_PROTOCOL_INFO,
847  FROM_PROTOCOL_INFO,
848  &src->wsainfo,
849  0,
850  0);
851  if (s == INVALID_SOCKET)
852  {
853  write_stderr("could not create inherited socket: error code %d\n",
854  WSAGetLastError());
855  exit(1);
856  }
857  *dest = s;
858 
859  /*
860  * To make sure we don't get two references to the same socket, close
861  * the original one. (This would happen when inheritance actually
862  * works..
863  */
864  closesocket(src->origsocket);
865  }
866 }
867 #endif
868 
869 static void
870 read_backend_variables(char *id, char **startup_data, size_t *startup_data_len)
871 {
872  BackendParameters param;
873 
874 #ifndef WIN32
875  /* Non-win32 implementation reads from file */
876  FILE *fp;
877 
878  /* Open file */
879  fp = AllocateFile(id, PG_BINARY_R);
880  if (!fp)
881  {
882  write_stderr("could not open backend variables file \"%s\": %m\n", id);
883  exit(1);
884  }
885 
886  if (fread(&param, sizeof(param), 1, fp) != 1)
887  {
888  write_stderr("could not read from backend variables file \"%s\": %m\n", id);
889  exit(1);
890  }
891 
892  /* read startup data */
893  *startup_data_len = param.startup_data_len;
894  if (param.startup_data_len > 0)
895  {
896  *startup_data = palloc(*startup_data_len);
897  if (fread(*startup_data, *startup_data_len, 1, fp) != 1)
898  {
899  write_stderr("could not read startup data from backend variables file \"%s\": %m\n",
900  id);
901  exit(1);
902  }
903  }
904  else
905  *startup_data = NULL;
906 
907  /* Release file */
908  FreeFile(fp);
909  if (unlink(id) != 0)
910  {
911  write_stderr("could not remove file \"%s\": %m\n", id);
912  exit(1);
913  }
914 #else
915  /* Win32 version uses mapped file */
916  HANDLE paramHandle;
917  BackendParameters *paramp;
918 
919 #ifdef _WIN64
920  paramHandle = (HANDLE) _atoi64(id);
921 #else
922  paramHandle = (HANDLE) atol(id);
923 #endif
924  paramp = MapViewOfFile(paramHandle, FILE_MAP_READ, 0, 0, 0);
925  if (!paramp)
926  {
927  write_stderr("could not map view of backend variables: error code %lu\n",
928  GetLastError());
929  exit(1);
930  }
931 
932  memcpy(&param, paramp, sizeof(BackendParameters));
933 
934  /* read startup data */
935  *startup_data_len = param.startup_data_len;
936  if (param.startup_data_len > 0)
937  {
938  *startup_data = palloc(paramp->startup_data_len);
939  memcpy(*startup_data, paramp->startup_data, param.startup_data_len);
940  }
941  else
942  *startup_data = NULL;
943 
944  if (!UnmapViewOfFile(paramp))
945  {
946  write_stderr("could not unmap view of backend variables: error code %lu\n",
947  GetLastError());
948  exit(1);
949  }
950 
951  if (!CloseHandle(paramHandle))
952  {
953  write_stderr("could not close handle to backend parameter variables: error code %lu\n",
954  GetLastError());
955  exit(1);
956  }
957 #endif
958 
959  restore_backend_variables(&param);
960 }
961 
962 /* Restore critical backend variables from the BackendParameters struct */
963 static void
964 restore_backend_variables(BackendParameters *param)
965 {
966  if (param->client_sock.sock != PGINVALID_SOCKET)
967  {
969  memcpy(MyClientSocket, &param->client_sock, sizeof(ClientSocket));
970  read_inheritable_socket(&MyClientSocket->sock, &param->inh_sock);
971  }
972 
973  SetDataDir(param->DataDir);
974 
975  MyPMChildSlot = param->MyPMChildSlot;
976 
977 #ifdef WIN32
978  ShmemProtectiveRegion = param->ShmemProtectiveRegion;
979 #endif
980  UsedShmemSegID = param->UsedShmemSegID;
981  UsedShmemSegAddr = param->UsedShmemSegAddr;
982 
983  ShmemLock = param->ShmemLock;
984 
985 #ifdef USE_INJECTION_POINTS
986  ActiveInjectionPoints = param->ActiveInjectionPoints;
987 #endif
988 
989  NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests;
990  NamedLWLockTrancheArray = param->NamedLWLockTrancheArray;
991  MainLWLockArray = param->MainLWLockArray;
992  ProcStructLock = param->ProcStructLock;
993  ProcGlobal = param->ProcGlobal;
994  AuxiliaryProcs = param->AuxiliaryProcs;
995  PreparedXactProcs = param->PreparedXactProcs;
996  PMSignalState = param->PMSignalState;
997  ProcSignal = param->ProcSignal;
998 
999  PostmasterPid = param->PostmasterPid;
1000  PgStartTime = param->PgStartTime;
1001  PgReloadTime = param->PgReloadTime;
1002  first_syslogger_file_time = param->first_syslogger_file_time;
1003 
1004  redirection_done = param->redirection_done;
1005  IsBinaryUpgrade = param->IsBinaryUpgrade;
1006  query_id_enabled = param->query_id_enabled;
1007  max_safe_fds = param->max_safe_fds;
1008 
1009  MaxBackends = param->MaxBackends;
1010  num_pmchild_slots = param->num_pmchild_slots;
1011 
1012 #ifdef WIN32
1013  PostmasterHandle = param->PostmasterHandle;
1014  pgwin32_initial_signal_pipe = param->initial_signal_pipe;
1015 #else
1016  memcpy(&postmaster_alive_fds, &param->postmaster_alive_fds,
1017  sizeof(postmaster_alive_fds));
1018 #endif
1019 
1020  memcpy(&syslogPipe, &param->syslogPipe, sizeof(syslogPipe));
1021 
1022  strlcpy(my_exec_path, param->my_exec_path, MAXPGPATH);
1023 
1024  strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
1025 
1026  /*
1027  * We need to restore fd.c's counts of externally-opened FDs; to avoid
1028  * confusion, be sure to do this after restoring max_safe_fds. (Note:
1029  * BackendInitialize will handle this for (*client_sock)->sock.)
1030  */
1031 #ifndef WIN32
1032  if (postmaster_alive_fds[0] >= 0)
1034  if (postmaster_alive_fds[1] >= 0)
1036 #endif
1037 }
1038 
1039 #endif /* EXEC_BACKEND */
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
void AutoVacWorkerMain(char *startup_data, size_t startup_data_len)
Definition: autovacuum.c:1361
void AutoVacLauncherMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn()
void StartupProcessMain(char *startup_data, size_t startup_data_len)
Definition: startup.c:216
TimestampTz PgReloadTime
Definition: timestamp.c:56
TimestampTz PgStartTime
Definition: timestamp.c:53
void BackendMain(char *startup_data, size_t startup_data_len)
void BackgroundWorkerMain(char *startup_data, size_t startup_data_len)
Definition: bgworker.c:717
void BackgroundWriterMain(char *startup_data, size_t startup_data_len)
Definition: bgwriter.c:87
#define write_stderr(str)
Definition: parallel.c:186
#define PG_BINARY_R
Definition: c.h:1254
#define Assert(condition)
Definition: c.h:837
#define pg_attribute_noreturn()
Definition: c.h:232
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:413
#define pg_unreachable()
Definition: c.h:311
#define lengthof(array)
Definition: c.h:767
#define PG_BINARY_W
Definition: c.h:1255
void CheckpointerMain(char *startup_data, size_t startup_data_len)
Definition: checkpointer.c:173
int64 TimestampTz
Definition: timestamp.h:39
@ DestNone
Definition: dest.h:87
void dsm_detach_all(void)
Definition: dsm.c:775
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode_for_file_access(void)
Definition: elog.c:876
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define LOG
Definition: elog.h:31
#define FATAL
Definition: elog.h:41
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3936
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2605
int max_safe_fds
Definition: fd.c:158
int FreeFile(FILE *file)
Definition: fd.c:2803
void ReserveExternalFD(void)
Definition: fd.c:1220
#define PG_TEMP_FILES_DIR
Definition: file_utils.h:62
#define PG_TEMP_FILE_PREFIX
Definition: file_utils.h:63
pid_t fork_process(void)
Definition: fork_process.c:32
struct ClientSocket * MyClientSocket
Definition: globals.c:49
bool IsBinaryUpgrade
Definition: globals.c:120
int MyPMChildSlot
Definition: globals.c:53
pid_t PostmasterPid
Definition: globals.c:105
int MyProcPid
Definition: globals.c:46
char pkglib_path[MAXPGPATH]
Definition: globals.c:81
bool IsUnderPostmaster
Definition: globals.c:119
int MaxBackends
Definition: globals.c:145
char * DataDir
Definition: globals.c:70
bool IsPostmasterEnvironment
Definition: globals.c:118
char my_exec_path[MAXPGPATH]
Definition: globals.c:80
void InitializeGUCOptions(void)
Definition: guc.c:1530
static child_process_kind child_process_kinds[]
const char * PostmasterChildName(BackendType child_type)
pid_t postmaster_child_launch(BackendType child_type, int child_slot, char *startup_data, size_t startup_data_len, ClientSocket *client_sock)
exit(1)
NamedLWLockTranche * NamedLWLockTrancheArray
Definition: lwlock.c:227
int NamedLWLockTrancheRequests
Definition: lwlock.c:224
LWLockPadded * MainLWLockArray
Definition: lwlock.c:188
void pfree(void *pointer)
Definition: mcxt.c:1521
MemoryContext TopMemoryContext
Definition: mcxt.c:149
void * palloc0(Size size)
Definition: mcxt.c:1347
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
void * palloc(Size size)
Definition: mcxt.c:1317
BackendType
Definition: miscadmin.h:331
@ B_WAL_SUMMARIZER
Definition: miscadmin.h:358
@ B_WAL_WRITER
Definition: miscadmin.h:359
@ B_WAL_RECEIVER
Definition: miscadmin.h:357
@ B_CHECKPOINTER
Definition: miscadmin.h:355
@ B_WAL_SENDER
Definition: miscadmin.h:340
@ B_LOGGER
Definition: miscadmin.h:365
@ B_STARTUP
Definition: miscadmin.h:356
@ B_BG_WORKER
Definition: miscadmin.h:339
@ B_INVALID
Definition: miscadmin.h:332
@ B_STANDALONE_BACKEND
Definition: miscadmin.h:343
@ B_BG_WRITER
Definition: miscadmin.h:354
@ B_BACKEND
Definition: miscadmin.h:335
@ B_ARCHIVER
Definition: miscadmin.h:353
@ B_AUTOVAC_LAUNCHER
Definition: miscadmin.h:337
@ B_SLOTSYNC_WORKER
Definition: miscadmin.h:341
@ B_DEAD_END_BACKEND
Definition: miscadmin.h:336
@ B_AUTOVAC_WORKER
Definition: miscadmin.h:338
void InitPostmasterChild(void)
Definition: miscinit.c:96
void process_shared_preload_libraries(void)
Definition: miscinit.c:1904
void checkDataDir(void)
Definition: miscinit.c:351
void SetDataDir(const char *dir)
Definition: miscinit.c:444
#define MAXPGPATH
void PgArchiverMain(char *startup_data, size_t startup_data_len)
Definition: pgarch.c:215
int64 pg_time_t
Definition: pgtime.h:23
NON_EXEC_STATIC int num_pmchild_slots
Definition: pmchild.c:55
NON_EXEC_STATIC volatile PMSignalData * PMSignalState
Definition: pmsignal.c:84
#define sprintf
Definition: port.h:240
#define snprintf
Definition: port.h:238
#define PGINVALID_SOCKET
Definition: port.h:31
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define closesocket
Definition: port.h:349
CommandDest whereToSendOutput
Definition: postgres.c:90
bool redirection_done
Definition: postmaster.c:358
int postmaster_alive_fds[2]
Definition: postmaster.c:460
void ClosePostmasterPorts(bool am_syslogger)
Definition: postmaster.c:1817
NON_EXEC_STATIC ProcSignalHeader * ProcSignal
Definition: procsignal.c:104
bool query_id_enabled
MemoryContextSwitchTo(old_ctx)
void InitShmemAccess(PGShmemHeader *seghdr)
Definition: shmem.c:97
slock_t * ShmemLock
Definition: shmem.c:87
HANDLE pgwin32_create_signal_listener(pid_t pid)
Definition: signal.c:227
HANDLE pgwin32_initial_signal_pipe
Definition: signal.c:28
void ReplSlotSyncWorkerMain(char *startup_data, size_t startup_data_len)
Definition: slotsync.c:1329
PGPROC * PreparedXactProcs
Definition: proc.c:80
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:79
PROC_HDR * ProcGlobal
Definition: proc.c:78
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:75
pgsocket sock
Definition: libpq-be.h:244
Definition: proc.h:162
Definition: proc.h:382
void(* main_fn)(char *startup_data, size_t startup_data_len) pg_attribute_noreturn()
NON_EXEC_STATIC pg_time_t first_syslogger_file_time
Definition: syslogger.c:87
int syslogPipe[2]
Definition: syslogger.c:114
void SysLoggerMain(char *startup_data, size_t startup_data_len)
Definition: syslogger.c:165
void PGSharedMemoryDetach(void)
Definition: sysv_shmem.c:970
unsigned long UsedShmemSegID
Definition: sysv_shmem.c:94
void * UsedShmemSegAddr
Definition: sysv_shmem.c:95
const char * name
void WalReceiverMain(char *startup_data, size_t startup_data_len)
Definition: walreceiver.c:183
void WalSummarizerMain(char *startup_data, size_t startup_data_len)
void WalWriterMain(char *startup_data, size_t startup_data_len)
Definition: walwriter.c:87
void PGSharedMemoryReAttach(void)
Definition: win32_shmem.c:424
void * ShmemProtectiveRegion
Definition: win32_shmem.c:42
int pgwin32_ReserveSharedMemoryRegion(HANDLE hChild)
Definition: win32_shmem.c:573
void PGSharedMemoryNoReAttach(void)
Definition: win32_shmem.c:472
void LocalProcessControlFile(bool reset)
Definition: xlog.c:4846