PostgreSQL Source Code: src/backend/postmaster/launch_backend.c Source File

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

AltStyle によって変換されたページ (->オリジナル) /