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