Line data Source code
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
76 : typedef struct
77 : {
78 : SOCKET origsocket; /* Original socket value, or PGINVALID_SOCKET
79 : * if not a socket */
80 : WSAPROTOCOL_INFO wsainfo;
81 : } InheritableSocket;
82 : #else
83 : typedef int InheritableSocket;
84 : #endif
85 :
86 : /*
87 : * Structure contains all variables passed to exec:ed backends
88 : */
89 : typedef 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 :
155 : static void read_backend_variables(char *id, void **startup_data, size_t *startup_data_len);
156 : static void restore_backend_variables(BackendParameters *param);
157 :
158 : static 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 :
165 : static 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 :
188 : const char *
189 1974 : PostmasterChildName(BackendType child_type)
190 : {
191 1974 : 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 : */
206 : pid_t
207 50622 : 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 50622 : if (IsExternalConnectionBackend(child_type))
217 26510 : ((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 50622 : pid = fork_process();
225 95390 : if (pid == 0) /* child */
226 : {
227 : /* Capture and transfer timings that may be needed for logging */
228 44768 : if (IsExternalConnectionBackend(child_type))
229 : {
230 25978 : conn_timing.socket_create =
231 25978 : ((BackendStartupData *) startup_data)->socket_created;
232 25978 : conn_timing.fork_start =
233 25978 : ((BackendStartupData *) startup_data)->fork_started;
234 25978 : conn_timing.fork_end = GetCurrentTimestamp();
235 : }
236 :
237 : /* Close the postmaster's sockets */
238 44768 : ClosePostmasterPorts(child_type == B_LOGGER);
239 :
240 : /* Detangle from postmaster */
241 44768 : InitPostmasterChild();
242 :
243 : /* Detach shared memory if not needed. */
244 44768 : if (!child_process_kinds[child_type].shmem_attach)
245 : {
246 2 : dsm_detach_all();
247 2 : 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 44768 : MemoryContextSwitchTo(TopMemoryContext);
257 :
258 44768 : MyPMChildSlot = child_slot;
259 44768 : if (client_sock)
260 : {
261 26548 : MyClientSocket = palloc(sizeof(ClientSocket));
262 26548 : memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
263 : }
264 :
265 : /*
266 : * Run the appropriate Main function
267 : */
268 44768 : child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
269 0 : pg_unreachable(); /* main_fn never returns */
270 : }
271 : #endif /* EXEC_BACKEND */
272 50622 : 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 : */
284 : static pid_t
285 : internal_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 : */
394 : static pid_t
395 : internal_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 */
412 : retry:
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 : */
575 : void
576 : SubPostmasterMain(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
699 : static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
700 : static bool write_inheritable_socket(InheritableSocket *dest, SOCKET src,
701 : pid_t childPid);
702 : static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
703 : #endif
704 :
705 :
706 : /* Save critical backend variables into the BackendParameters struct */
707 : static bool
708 : save_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(¶m->client_sock, client_sock, sizeof(ClientSocket));
717 : else
718 : memset(¶m->client_sock, 0, sizeof(ClientSocket));
719 : if (!write_inheritable_socket(¶m->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(¶m->initial_signal_pipe,
768 : pgwin32_create_signal_listener(childPid),
769 : childProcess))
770 : return false;
771 : #else
772 : memcpy(¶m->postmaster_alive_fds, &postmaster_alive_fds,
773 : sizeof(postmaster_alive_fds));
774 : #endif
775 :
776 : memcpy(¶m->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 : */
794 : static bool
795 : write_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 : */
824 : static bool
825 : write_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 : */
845 : static void
846 : read_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 :
882 : static void
883 : read_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(¶m, 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(¶m, 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(¶m);
973 : }
974 :
975 : /* Restore critical backend variables from the BackendParameters struct */
976 : static void
977 : restore_backend_variables(BackendParameters *param)
978 : {
979 : if (param->client_sock.sock != PGINVALID_SOCKET)
980 : {
981 : MyClientSocket = MemoryContextAlloc(TopMemoryContext, sizeof(ClientSocket));
982 : memcpy(MyClientSocket, ¶m->client_sock, sizeof(ClientSocket));
983 : read_inheritable_socket(&MyClientSocket->sock, ¶m->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, ¶m->postmaster_alive_fds,
1032 : sizeof(postmaster_alive_fds));
1033 : #endif
1034 :
1035 : memcpy(&syslogPipe, ¶m->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 */
|