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