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