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