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 : NamedLWLockTranche *NamedLWLockTrancheArray;
105 : int *LWLockCounter;
106 : LWLockPadded *MainLWLockArray;
107 : slock_t *ProcStructLock;
108 : PROC_HDR *ProcGlobal;
109 : PGPROC *AuxiliaryProcs;
110 : PGPROC *PreparedXactProcs;
111 : volatile PMSignalData *PMSignalState;
112 : ProcSignalHeader *ProcSignal;
113 : pid_t PostmasterPid;
114 : TimestampTz PgStartTime;
115 : TimestampTz PgReloadTime;
116 : pg_time_t first_syslogger_file_time;
117 : bool redirection_done;
118 : bool IsBinaryUpgrade;
119 : bool query_id_enabled;
120 : int max_safe_fds;
121 : int MaxBackends;
122 : int num_pmchild_slots;
123 : #ifdef WIN32
124 : HANDLE PostmasterHandle;
125 : HANDLE initial_signal_pipe;
126 : HANDLE syslogPipe[2];
127 : #else
128 : int postmaster_alive_fds[2];
129 : int syslogPipe[2];
130 : #endif
131 : char my_exec_path[MAXPGPATH];
132 : char pkglib_path[MAXPGPATH];
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 :
154 : static void read_backend_variables(char *id, void **startup_data, size_t *startup_data_len);
155 : static void restore_backend_variables(BackendParameters *param);
156 :
157 : static 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 :
164 : static 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 : */
173 : typedef struct
174 : {
175 : const char *name;
176 : void (*main_fn) (const void *startup_data, size_t startup_data_len);
177 : bool shmem_attach;
178 : } child_process_kind;
179 :
180 : static child_process_kind child_process_kinds[] = {
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 :
211 : const char *
212 1914 : PostmasterChildName(BackendType child_type)
213 : {
214 1914 : 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 : */
229 : pid_t
230 50778 : postmaster_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 :
236 : Assert(IsPostmasterEnvironment && !IsUnderPostmaster);
237 :
238 : /* Capture time Postmaster initiates process creation for logging */
239 50778 : if (IsExternalConnectionBackend(child_type))
240 26312 : ((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 50778 : pid = fork_process();
248 95586 : if (pid == 0) /* child */
249 : {
250 : /* Capture and transfer timings that may be needed for logging */
251 44808 : if (IsExternalConnectionBackend(child_type))
252 : {
253 25694 : conn_timing.socket_create =
254 25694 : ((BackendStartupData *) startup_data)->socket_created;
255 25694 : conn_timing.fork_start =
256 25694 : ((BackendStartupData *) startup_data)->fork_started;
257 25694 : conn_timing.fork_end = GetCurrentTimestamp();
258 : }
259 :
260 : /* Close the postmaster's sockets */
261 44808 : ClosePostmasterPorts(child_type == B_LOGGER);
262 :
263 : /* Detangle from postmaster */
264 44808 : InitPostmasterChild();
265 :
266 : /* Detach shared memory if not needed. */
267 44808 : if (!child_process_kinds[child_type].shmem_attach)
268 : {
269 2 : dsm_detach_all();
270 2 : PGSharedMemoryDetach();
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 : */
279 44808 : MemoryContextSwitchTo(TopMemoryContext);
280 :
281 44808 : MyPMChildSlot = child_slot;
282 44808 : if (client_sock)
283 : {
284 26302 : MyClientSocket = palloc(sizeof(ClientSocket));
285 26302 : memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
286 : }
287 :
288 : /*
289 : * Run the appropriate Main function
290 : */
291 44808 : child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
292 0 : pg_unreachable(); /* main_fn never returns */
293 : }
294 : #endif /* EXEC_BACKEND */
295 50778 : 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 : */
307 : static pid_t
308 : internal_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",
337 : PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
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 : */
348 : (void) MakePGDirectory(PG_TEMP_FILES_DIR);
349 :
350 : fp = AllocateFile(tmpfilename, PG_BINARY_W);
351 : if (!fp)
352 : {
353 : ereport(LOG,
354 : (errcode_for_file_access(),
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,
365 : (errcode_for_file_access(),
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,
377 : (errcode_for_file_access(),
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 : */
417 : static pid_t
418 : internal_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 */
435 : retry:
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 : */
598 : void
599 : SubPostmasterMain(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 */
609 : IsPostmasterEnvironment = true;
610 : whereToSendOutput = DestNone;
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) */
619 : InitializeGUCOptions();
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 */
649 : InitPostmasterChild();
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)
668 : PGSharedMemoryReAttach();
669 : else
670 : PGSharedMemoryNoReAttach();
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 : {
678 : conn_timing.socket_create =
679 : ((BackendStartupData *) startup_data)->socket_created;
680 : conn_timing.fork_start =
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 : */
697 : LocalProcessControlFile(false);
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 : */
705 : process_shared_preload_libraries();
706 :
707 : /* Restore basic shared memory pointers */
708 : if (UsedShmemSegAddr != NULL)
709 : InitShmemAccess(UsedShmemSegAddr);
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
722 : static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
723 : static bool write_inheritable_socket(InheritableSocket *dest, SOCKET src,
724 : pid_t childPid);
725 : static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
726 : #endif
727 :
728 :
729 : /* Save critical backend variables into the BackendParameters struct */
730 : static bool
731 : save_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(¶m->client_sock, client_sock, sizeof(ClientSocket));
740 : else
741 : memset(¶m->client_sock, 0, sizeof(ClientSocket));
742 : if (!write_inheritable_socket(¶m->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->LWLockCounter = LWLockCounter;
766 : param->MainLWLockArray = MainLWLockArray;
767 : param->ProcStructLock = ProcStructLock;
768 : param->ProcGlobal = ProcGlobal;
769 : param->AuxiliaryProcs = AuxiliaryProcs;
770 : param->PreparedXactProcs = PreparedXactProcs;
771 : param->PMSignalState = PMSignalState;
772 : param->ProcSignal = ProcSignal;
773 :
774 : param->PostmasterPid = PostmasterPid;
775 : param->PgStartTime = PgStartTime;
776 : param->PgReloadTime = PgReloadTime;
777 : param->first_syslogger_file_time = first_syslogger_file_time;
778 :
779 : param->redirection_done = redirection_done;
780 : param->IsBinaryUpgrade = IsBinaryUpgrade;
781 : param->query_id_enabled = query_id_enabled;
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(¶m->initial_signal_pipe,
790 : pgwin32_create_signal_listener(childPid),
791 : childProcess))
792 : return false;
793 : #else
794 : memcpy(¶m->postmaster_alive_fds, &postmaster_alive_fds,
795 : sizeof(postmaster_alive_fds));
796 : #endif
797 :
798 : memcpy(¶m->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 : */
816 : static bool
817 : write_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 : */
846 : static bool
847 : write_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 : */
867 : static void
868 : read_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 :
904 : static void
905 : read_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(¶m, 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(¶m, 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(¶m);
995 : }
996 :
997 : /* Restore critical backend variables from the BackendParameters struct */
998 : static void
999 : restore_backend_variables(BackendParameters *param)
1000 : {
1001 : if (param->client_sock.sock != PGINVALID_SOCKET)
1002 : {
1003 : MyClientSocket = MemoryContextAlloc(TopMemoryContext, sizeof(ClientSocket));
1004 : memcpy(MyClientSocket, ¶m->client_sock, sizeof(ClientSocket));
1005 : read_inheritable_socket(&MyClientSocket->sock, ¶m->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 : LWLockCounter = param->LWLockCounter;
1027 : MainLWLockArray = param->MainLWLockArray;
1028 : ProcStructLock = param->ProcStructLock;
1029 : ProcGlobal = param->ProcGlobal;
1030 : AuxiliaryProcs = param->AuxiliaryProcs;
1031 : PreparedXactProcs = param->PreparedXactProcs;
1032 : PMSignalState = param->PMSignalState;
1033 : ProcSignal = param->ProcSignal;
1034 :
1035 : PostmasterPid = param->PostmasterPid;
1036 : PgStartTime = param->PgStartTime;
1037 : PgReloadTime = param->PgReloadTime;
1038 : first_syslogger_file_time = param->first_syslogger_file_time;
1039 :
1040 : redirection_done = param->redirection_done;
1041 : IsBinaryUpgrade = param->IsBinaryUpgrade;
1042 : query_id_enabled = param->query_id_enabled;
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, ¶m->postmaster_alive_fds,
1053 : sizeof(postmaster_alive_fds));
1054 : #endif
1055 :
1056 : memcpy(&syslogPipe, ¶m->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)
1069 : ReserveExternalFD();
1070 : if (postmaster_alive_fds[1] >= 0)
1071 : ReserveExternalFD();
1072 : #endif
1073 : }
1074 :
1075 : #endif /* EXEC_BACKEND */
|