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