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