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