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