Branch data 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 : : slock_t *ShmemLock;
100 : : #ifdef USE_INJECTION_POINTS
101 : : struct InjectionPointsCtl *ActiveInjectionPoints;
102 : : #endif
103 : : int NamedLWLockTrancheRequests;
104 : : NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray;
105 : : char **LWLockTrancheNames;
106 : : int *LWLockCounter;
107 : : LWLockPadded *MainLWLockArray;
108 : : slock_t *ProcStructLock;
109 : : PROC_HDR *ProcGlobal;
110 : : PGPROC *AuxiliaryProcs;
111 : : PGPROC *PreparedXactProcs;
112 : : volatile PMSignalData *PMSignalState;
113 : : ProcSignalHeader *ProcSignal;
114 : : pid_t PostmasterPid;
115 : : TimestampTz PgStartTime;
116 : : TimestampTz PgReloadTime;
117 : : pg_time_t first_syslogger_file_time;
118 : : bool redirection_done;
119 : : bool IsBinaryUpgrade;
120 : : bool query_id_enabled;
121 : : int max_safe_fds;
122 : : int MaxBackends;
123 : : int num_pmchild_slots;
124 : : #ifdef WIN32
125 : : HANDLE PostmasterHandle;
126 : : HANDLE initial_signal_pipe;
127 : : HANDLE syslogPipe[2];
128 : : #else
129 : : int postmaster_alive_fds[2];
130 : : int syslogPipe[2];
131 : : #endif
132 : : char my_exec_path[MAXPGPATH];
133 : : char pkglib_path[MAXPGPATH];
134 : :
135 : : int MyPMChildSlot;
136 : :
137 : : /*
138 : : * These are only used by backend processes, but are here because passing
139 : : * a socket needs some special handling on Windows. 'client_sock' is an
140 : : * explicit argument to postmaster_child_launch, but is stored in
141 : : * MyClientSocket in the child process.
142 : : */
143 : : ClientSocket client_sock;
144 : : InheritableSocket inh_sock;
145 : :
146 : : /*
147 : : * Extra startup data, content depends on the child process.
148 : : */
149 : : size_t startup_data_len;
150 : : char startup_data[FLEXIBLE_ARRAY_MEMBER];
151 : : } BackendParameters;
152 : :
153 : : #define SizeOfBackendParameters(startup_data_len) (offsetof(BackendParameters, startup_data) + startup_data_len)
154 : :
155 : : static void read_backend_variables(char *id, void **startup_data, size_t *startup_data_len);
156 : : static void restore_backend_variables(BackendParameters *param);
157 : :
158 : : static bool save_backend_variables(BackendParameters *param, int child_slot,
159 : : ClientSocket *client_sock,
160 : : #ifdef WIN32
161 : : HANDLE childProcess, pid_t childPid,
162 : : #endif
163 : : const void *startup_data, size_t startup_data_len);
164 : :
165 : : static pid_t internal_forkexec(BackendType child_kind, int child_slot,
166 : : const void *startup_data, size_t startup_data_len,
167 : : ClientSocket *client_sock);
168 : :
169 : : #endif /* EXEC_BACKEND */
170 : :
171 : : /*
172 : : * Information needed to launch different kinds of child processes.
173 : : */
174 : : typedef struct
175 : : {
176 : : const char *name;
177 : : void (*main_fn) (const void *startup_data, size_t startup_data_len);
178 : : bool shmem_attach;
179 : : } child_process_kind;
180 : :
181 : : static child_process_kind child_process_kinds[] = {
182 : : #define PG_PROCTYPE(bktype, description, main_func, shmem_attach) \
183 : : [bktype] = {description, main_func, shmem_attach},
184 : : #include "postmaster/proctypelist.h"
185 : : #undef PG_PROCTYPE
186 : : };
187 : :
188 : : const char *
189 : 0 : PostmasterChildName(BackendType child_type)
190 : : {
191 : 0 : return child_process_kinds[child_type].name;
192 : : }
193 : :
194 : : /*
195 : : * Start a new postmaster child process.
196 : : *
197 : : * The child process will be restored to roughly the same state whether
198 : : * EXEC_BACKEND is used or not: it will be attached to shared memory if
199 : : * appropriate, and fds and other resources that we've inherited from
200 : : * postmaster that are not needed in a child process have been closed.
201 : : *
202 : : * 'child_slot' is the PMChildFlags array index reserved for the child
203 : : * process. 'startup_data' is an optional contiguous chunk of data that is
204 : : * passed to the child process.
205 : : */
206 : : pid_t
207 : 812 : postmaster_child_launch(BackendType child_type, int child_slot,
208 : : void *startup_data, size_t startup_data_len,
209 : : ClientSocket *client_sock)
210 : : {
211 : 812 : pid_t pid;
212 : :
213 [ + - ]: 812 : Assert(IsPostmasterEnvironment && !IsUnderPostmaster);
214 : :
215 : : /* Capture time Postmaster initiates process creation for logging */
216 [ + + - + ]: 812 : if (IsExternalConnectionBackend(child_type))
217 : 316 : ((BackendStartupData *) startup_data)->fork_started = GetCurrentTimestamp();
218 : :
219 : : #ifdef EXEC_BACKEND
220 : : pid = internal_forkexec(child_type, child_slot,
221 : : startup_data, startup_data_len, client_sock);
222 : : /* the child process will arrive in SubPostmasterMain */
223 : : #else /* !EXEC_BACKEND */
224 : 812 : pid = fork_process();
225 [ + + ]: 812 : if (pid == 0) /* child */
226 : : {
227 : : /* Capture and transfer timings that may be needed for logging */
228 [ + + - + ]: 804 : if (IsExternalConnectionBackend(child_type))
229 : : {
230 : 315 : conn_timing.socket_create =
231 : 315 : ((BackendStartupData *) startup_data)->socket_created;
232 : 315 : conn_timing.fork_start =
233 : 315 : ((BackendStartupData *) startup_data)->fork_started;
234 : 315 : conn_timing.fork_end = GetCurrentTimestamp();
235 : 315 : }
236 : :
237 : : /* Close the postmaster's sockets */
238 : 804 : ClosePostmasterPorts(child_type == B_LOGGER);
239 : :
240 : : /* Detangle from postmaster */
241 : 804 : InitPostmasterChild();
242 : :
243 : : /* Detach shared memory if not needed. */
244 [ + - ]: 804 : if (!child_process_kinds[child_type].shmem_attach)
245 : : {
246 : 0 : dsm_detach_all();
247 : 0 : PGSharedMemoryDetach();
248 : 0 : }
249 : :
250 : : /*
251 : : * Enter the Main function with TopMemoryContext. The startup data is
252 : : * allocated in PostmasterContext, so we cannot release it here yet.
253 : : * The Main function will do it after it's done handling the startup
254 : : * data.
255 : : */
256 : 804 : MemoryContextSwitchTo(TopMemoryContext);
257 : :
258 : 804 : MyPMChildSlot = child_slot;
259 [ + + ]: 804 : if (client_sock)
260 : : {
261 : 315 : MyClientSocket = palloc_object(ClientSocket);
262 : 315 : memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
263 : 315 : }
264 : :
265 : : /*
266 : : * Run the appropriate Main function
267 : : */
268 : 804 : child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
269 : 804 : pg_unreachable(); /* main_fn never returns */
270 : : }
271 : : #endif /* EXEC_BACKEND */
272 : 16 : return pid;
273 : 8 : }
274 : :
275 : : #ifdef EXEC_BACKEND
276 : : #ifndef WIN32
277 : :
278 : : /*
279 : : * internal_forkexec non-win32 implementation
280 : : *
281 : : * - writes out backend variables to the parameter file
282 : : * - fork():s, and then exec():s the child process
283 : : */
284 : : static pid_t
285 : : internal_forkexec(BackendType child_kind, int child_slot,
286 : : const void *startup_data, size_t startup_data_len, ClientSocket *client_sock)
287 : : {
288 : : static unsigned long tmpBackendFileNum = 0;
289 : : pid_t pid;
290 : : char tmpfilename[MAXPGPATH];
291 : : size_t paramsz;
292 : : BackendParameters *param;
293 : : FILE *fp;
294 : : char *argv[4];
295 : : char forkav[MAXPGPATH];
296 : :
297 : : /*
298 : : * Use palloc0 to make sure padding bytes are initialized, to prevent
299 : : * Valgrind from complaining about writing uninitialized bytes to the
300 : : * file. This isn't performance critical, and the win32 implementation
301 : : * initializes the padding bytes to zeros, so do it even when not using
302 : : * Valgrind.
303 : : */
304 : : paramsz = SizeOfBackendParameters(startup_data_len);
305 : : param = palloc0(paramsz);
306 : : if (!save_backend_variables(param, child_slot, client_sock, startup_data, startup_data_len))
307 : : {
308 : : pfree(param);
309 : : return -1; /* log made by save_backend_variables */
310 : : }
311 : :
312 : : /* Calculate name for temp file */
313 : : snprintf(tmpfilename, MAXPGPATH, "%s/%s.backend_var.%d.%lu",
314 : : PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
315 : : MyProcPid, ++tmpBackendFileNum);
316 : :
317 : : /* Open file */
318 : : fp = AllocateFile(tmpfilename, PG_BINARY_W);
319 : : if (!fp)
320 : : {
321 : : /*
322 : : * As in OpenTemporaryFileInTablespace, try to make the temp-file
323 : : * directory, ignoring errors.
324 : : */
325 : : (void) MakePGDirectory(PG_TEMP_FILES_DIR);
326 : :
327 : : fp = AllocateFile(tmpfilename, PG_BINARY_W);
328 : : if (!fp)
329 : : {
330 : : ereport(LOG,
331 : : (errcode_for_file_access(),
332 : : errmsg("could not create file \"%s\": %m",
333 : : tmpfilename)));
334 : : pfree(param);
335 : : return -1;
336 : : }
337 : : }
338 : :
339 : : if (fwrite(param, paramsz, 1, fp) != 1)
340 : : {
341 : : ereport(LOG,
342 : : (errcode_for_file_access(),
343 : : errmsg("could not write to file \"%s\": %m", tmpfilename)));
344 : : FreeFile(fp);
345 : : pfree(param);
346 : : return -1;
347 : : }
348 : : pfree(param);
349 : :
350 : : /* Release file */
351 : : if (FreeFile(fp))
352 : : {
353 : : ereport(LOG,
354 : : (errcode_for_file_access(),
355 : : errmsg("could not write to file \"%s\": %m", tmpfilename)));
356 : : return -1;
357 : : }
358 : :
359 : : /* set up argv properly */
360 : : argv[0] = "postgres";
361 : : snprintf(forkav, MAXPGPATH, "--forkchild=%d", (int) child_kind);
362 : : argv[1] = forkav;
363 : : /* Insert temp file name after --forkchild argument */
364 : : argv[2] = tmpfilename;
365 : : argv[3] = NULL;
366 : :
367 : : /* Fire off execv in child */
368 : : if ((pid = fork_process()) == 0)
369 : : {
370 : : if (execv(postgres_exec_path, argv) < 0)
371 : : {
372 : : ereport(LOG,
373 : : (errmsg("could not execute server process \"%s\": %m",
374 : : postgres_exec_path)));
375 : : /* We're already in the child process here, can't return */
376 : : exit(1);
377 : : }
378 : : }
379 : :
380 : : return pid; /* Parent returns pid, or -1 on fork failure */
381 : : }
382 : : #else /* WIN32 */
383 : :
384 : : /*
385 : : * internal_forkexec win32 implementation
386 : : *
387 : : * - starts backend using CreateProcess(), in suspended state
388 : : * - writes out backend variables to the parameter file
389 : : * - during this, duplicates handles and sockets required for
390 : : * inheritance into the new process
391 : : * - resumes execution of the new process once the backend parameter
392 : : * file is complete.
393 : : */
394 : : static pid_t
395 : : internal_forkexec(BackendType child_kind, int child_slot,
396 : : const void *startup_data, size_t startup_data_len, ClientSocket *client_sock)
397 : : {
398 : : int retry_count = 0;
399 : : STARTUPINFO si;
400 : : PROCESS_INFORMATION pi;
401 : : char cmdLine[MAXPGPATH * 2];
402 : : HANDLE paramHandle;
403 : : BackendParameters *param;
404 : : SECURITY_ATTRIBUTES sa;
405 : : size_t paramsz;
406 : : char paramHandleStr[32];
407 : : int l;
408 : :
409 : : paramsz = SizeOfBackendParameters(startup_data_len);
410 : :
411 : : /* Resume here if we need to retry */
412 : : retry:
413 : :
414 : : /* Set up shared memory for parameter passing */
415 : : ZeroMemory(&sa, sizeof(sa));
416 : : sa.nLength = sizeof(sa);
417 : : sa.bInheritHandle = TRUE;
418 : : paramHandle = CreateFileMapping(INVALID_HANDLE_VALUE,
419 : : &sa,
420 : : PAGE_READWRITE,
421 : : 0,
422 : : paramsz,
423 : : NULL);
424 : : if (paramHandle == INVALID_HANDLE_VALUE)
425 : : {
426 : : ereport(LOG,
427 : : (errmsg("could not create backend parameter file mapping: error code %lu",
428 : : GetLastError())));
429 : : return -1;
430 : : }
431 : : param = MapViewOfFile(paramHandle, FILE_MAP_WRITE, 0, 0, paramsz);
432 : : if (!param)
433 : : {
434 : : ereport(LOG,
435 : : (errmsg("could not map backend parameter memory: error code %lu",
436 : : GetLastError())));
437 : : CloseHandle(paramHandle);
438 : : return -1;
439 : : }
440 : :
441 : : /* Format the cmd line */
442 : : #ifdef _WIN64
443 : : sprintf(paramHandleStr, "%llu", (LONG_PTR) paramHandle);
444 : : #else
445 : : sprintf(paramHandleStr, "%lu", (DWORD) paramHandle);
446 : : #endif
447 : : l = snprintf(cmdLine, sizeof(cmdLine) - 1, "\"%s\" --forkchild=%d %s",
448 : : postgres_exec_path, (int) child_kind, paramHandleStr);
449 : : if (l >= sizeof(cmdLine))
450 : : {
451 : : ereport(LOG,
452 : : (errmsg("subprocess command line too long")));
453 : : UnmapViewOfFile(param);
454 : : CloseHandle(paramHandle);
455 : : return -1;
456 : : }
457 : :
458 : : memset(&pi, 0, sizeof(pi));
459 : : memset(&si, 0, sizeof(si));
460 : : si.cb = sizeof(si);
461 : :
462 : : /*
463 : : * Create the subprocess in a suspended state. This will be resumed later,
464 : : * once we have written out the parameter file.
465 : : */
466 : : if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, CREATE_SUSPENDED,
467 : : NULL, NULL, &si, &pi))
468 : : {
469 : : ereport(LOG,
470 : : (errmsg("CreateProcess() call failed: %m (error code %lu)",
471 : : GetLastError())));
472 : : UnmapViewOfFile(param);
473 : : CloseHandle(paramHandle);
474 : : return -1;
475 : : }
476 : :
477 : : if (!save_backend_variables(param, child_slot, client_sock,
478 : : pi.hProcess, pi.dwProcessId,
479 : : startup_data, startup_data_len))
480 : : {
481 : : /*
482 : : * log made by save_backend_variables, but we have to clean up the
483 : : * mess with the half-started process
484 : : */
485 : : if (!TerminateProcess(pi.hProcess, 255))
486 : : ereport(LOG,
487 : : (errmsg_internal("could not terminate unstarted process: error code %lu",
488 : : GetLastError())));
489 : : CloseHandle(pi.hProcess);
490 : : CloseHandle(pi.hThread);
491 : : UnmapViewOfFile(param);
492 : : CloseHandle(paramHandle);
493 : : return -1; /* log made by save_backend_variables */
494 : : }
495 : :
496 : : /* Drop the parameter shared memory that is now inherited to the backend */
497 : : if (!UnmapViewOfFile(param))
498 : : ereport(LOG,
499 : : (errmsg("could not unmap view of backend parameter file: error code %lu",
500 : : GetLastError())));
501 : : if (!CloseHandle(paramHandle))
502 : : ereport(LOG,
503 : : (errmsg("could not close handle to backend parameter file: error code %lu",
504 : : GetLastError())));
505 : :
506 : : /*
507 : : * Reserve the memory region used by our main shared memory segment before
508 : : * we resume the child process. Normally this should succeed, but if ASLR
509 : : * is active then it might sometimes fail due to the stack or heap having
510 : : * gotten mapped into that range. In that case, just terminate the
511 : : * process and retry.
512 : : */
513 : : if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
514 : : {
515 : : /* pgwin32_ReserveSharedMemoryRegion already made a log entry */
516 : : if (!TerminateProcess(pi.hProcess, 255))
517 : : ereport(LOG,
518 : : (errmsg_internal("could not terminate process that failed to reserve memory: error code %lu",
519 : : GetLastError())));
520 : : CloseHandle(pi.hProcess);
521 : : CloseHandle(pi.hThread);
522 : : if (++retry_count < 100)
523 : : goto retry;
524 : : ereport(LOG,
525 : : (errmsg("giving up after too many tries to reserve shared memory"),
526 : : errhint("This might be caused by ASLR or antivirus software.")));
527 : : return -1;
528 : : }
529 : :
530 : : /*
531 : : * Now that the backend variables are written out, we start the child
532 : : * thread so it can start initializing while we set up the rest of the
533 : : * parent state.
534 : : */
535 : : if (ResumeThread(pi.hThread) == -1)
536 : : {
537 : : if (!TerminateProcess(pi.hProcess, 255))
538 : : {
539 : : ereport(LOG,
540 : : (errmsg_internal("could not terminate unstartable process: error code %lu",
541 : : GetLastError())));
542 : : CloseHandle(pi.hProcess);
543 : : CloseHandle(pi.hThread);
544 : : return -1;
545 : : }
546 : : CloseHandle(pi.hProcess);
547 : : CloseHandle(pi.hThread);
548 : : ereport(LOG,
549 : : (errmsg_internal("could not resume thread of unstarted process: error code %lu",
550 : : GetLastError())));
551 : : return -1;
552 : : }
553 : :
554 : : /* Set up notification when the child process dies */
555 : : pgwin32_register_deadchild_callback(pi.hProcess, pi.dwProcessId);
556 : :
557 : : /* Don't close pi.hProcess, it's owned by the deadchild callback now */
558 : :
559 : : CloseHandle(pi.hThread);
560 : :
561 : : return pi.dwProcessId;
562 : : }
563 : : #endif /* WIN32 */
564 : :
565 : : /*
566 : : * SubPostmasterMain -- Get the fork/exec'd process into a state equivalent
567 : : * to what it would be if we'd simply forked on Unix, and then
568 : : * dispatch to the appropriate place.
569 : : *
570 : : * The first two command line arguments are expected to be "--forkchild=<kind>",
571 : : * where <kind> indicates which process type we are to become, and
572 : : * the name of a variables file that we can read to load data that would
573 : : * have been inherited by fork() on Unix.
574 : : */
575 : : void
576 : : SubPostmasterMain(int argc, char *argv[])
577 : : {
578 : : void *startup_data;
579 : : size_t startup_data_len;
580 : : char *child_kind;
581 : : BackendType child_type;
582 : : TimestampTz fork_end;
583 : :
584 : : /* In EXEC_BACKEND case we will not have inherited these settings */
585 : : IsPostmasterEnvironment = true;
586 : : whereToSendOutput = DestNone;
587 : :
588 : : /*
589 : : * Capture the end of process creation for logging. We don't include the
590 : : * time spent copying data from shared memory and setting up the backend.
591 : : */
592 : : fork_end = GetCurrentTimestamp();
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 : : /*
602 : : * Parse the --forkchild argument to find our process type. We rely with
603 : : * malice aforethought on atoi returning 0 (B_INVALID) on error.
604 : : */
605 : : if (strncmp(argv[1], "--forkchild=", 12) != 0)
606 : : elog(FATAL, "invalid subpostmaster invocation (--forkchild argument missing)");
607 : : child_kind = argv[1] + 12;
608 : : child_type = (BackendType) atoi(child_kind);
609 : : if (child_type <= B_INVALID || child_type > BACKEND_NUM_TYPES - 1)
610 : : elog(ERROR, "unknown child kind %s", child_kind);
611 : :
612 : : /* Read in the variables file */
613 : : read_backend_variables(argv[2], &startup_data, &startup_data_len);
614 : :
615 : : /* Close the postmaster's sockets (as soon as we know them) */
616 : : ClosePostmasterPorts(child_type == B_LOGGER);
617 : :
618 : : /* Setup as postmaster child */
619 : : InitPostmasterChild();
620 : :
621 : : /*
622 : : * If appropriate, physically re-attach to shared memory segment. We want
623 : : * to do this before going any further to ensure that we can attach at the
624 : : * same address the postmaster used. On the other hand, if we choose not
625 : : * to re-attach, we may have other cleanup to do.
626 : : *
627 : : * If testing EXEC_BACKEND on Linux, you should run this as root before
628 : : * starting the postmaster:
629 : : *
630 : : * sysctl -w kernel.randomize_va_space=0
631 : : *
632 : : * This prevents using randomized stack and code addresses that cause the
633 : : * child process's memory map to be different from the parent's, making it
634 : : * sometimes impossible to attach to shared memory at the desired address.
635 : : * Return the setting to its old value (usually '1' or '2') when finished.
636 : : */
637 : : if (child_process_kinds[child_type].shmem_attach)
638 : : PGSharedMemoryReAttach();
639 : : else
640 : : PGSharedMemoryNoReAttach();
641 : :
642 : : /* Read in remaining GUC variables */
643 : : read_nondefault_variables();
644 : :
645 : : /* Capture and transfer timings that may be needed for log_connections */
646 : : if (IsExternalConnectionBackend(child_type))
647 : : {
648 : : conn_timing.socket_create =
649 : : ((BackendStartupData *) startup_data)->socket_created;
650 : : conn_timing.fork_start =
651 : : ((BackendStartupData *) startup_data)->fork_started;
652 : : conn_timing.fork_end = fork_end;
653 : : }
654 : :
655 : : /*
656 : : * Check that the data directory looks valid, which will also check the
657 : : * privileges on the data directory and update our umask and file/group
658 : : * variables for creating files later. Note: this should really be done
659 : : * before we create any files or directories.
660 : : */
661 : : checkDataDir();
662 : :
663 : : /*
664 : : * (re-)read control file, as it contains config. The postmaster will
665 : : * already have read this, but this process doesn't know about that.
666 : : */
667 : : LocalProcessControlFile(false);
668 : :
669 : : /*
670 : : * Reload any libraries that were preloaded by the postmaster. Since we
671 : : * exec'd this process, those libraries didn't come along with us; but we
672 : : * should load them into all child processes to be consistent with the
673 : : * non-EXEC_BACKEND behavior.
674 : : */
675 : : process_shared_preload_libraries();
676 : :
677 : : /* Restore basic shared memory pointers */
678 : : if (UsedShmemSegAddr != NULL)
679 : : InitShmemAccess(UsedShmemSegAddr);
680 : :
681 : : /*
682 : : * Run the appropriate Main function
683 : : */
684 : : child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
685 : : pg_unreachable(); /* main_fn never returns */
686 : : }
687 : :
688 : : #ifndef WIN32
689 : : #define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
690 : : #define read_inheritable_socket(dest, src) (*(dest) = *(src))
691 : : #else
692 : : static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
693 : : static bool write_inheritable_socket(InheritableSocket *dest, SOCKET src,
694 : : pid_t childPid);
695 : : static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
696 : : #endif
697 : :
698 : :
699 : : /* Save critical backend variables into the BackendParameters struct */
700 : : static bool
701 : : save_backend_variables(BackendParameters *param,
702 : : int child_slot, ClientSocket *client_sock,
703 : : #ifdef WIN32
704 : : HANDLE childProcess, pid_t childPid,
705 : : #endif
706 : : const void *startup_data, size_t startup_data_len)
707 : : {
708 : : if (client_sock)
709 : : memcpy(¶m->client_sock, client_sock, sizeof(ClientSocket));
710 : : else
711 : : memset(¶m->client_sock, 0, sizeof(ClientSocket));
712 : : if (!write_inheritable_socket(¶m->inh_sock,
713 : : client_sock ? client_sock->sock : PGINVALID_SOCKET,
714 : : childPid))
715 : : return false;
716 : :
717 : : strlcpy(param->DataDir, DataDir, MAXPGPATH);
718 : :
719 : : param->MyPMChildSlot = child_slot;
720 : :
721 : : #ifdef WIN32
722 : : param->ShmemProtectiveRegion = ShmemProtectiveRegion;
723 : : #endif
724 : : param->UsedShmemSegID = UsedShmemSegID;
725 : : param->UsedShmemSegAddr = UsedShmemSegAddr;
726 : :
727 : : param->ShmemLock = ShmemLock;
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 : : ShmemLock = param->ShmemLock;
990 : :
991 : : #ifdef USE_INJECTION_POINTS
992 : : ActiveInjectionPoints = param->ActiveInjectionPoints;
993 : : #endif
994 : :
995 : : NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests;
996 : : NamedLWLockTrancheRequestArray = param->NamedLWLockTrancheRequestArray;
997 : : LWLockTrancheNames = param->LWLockTrancheNames;
998 : : LWLockCounter = param->LWLockCounter;
999 : : MainLWLockArray = param->MainLWLockArray;
1000 : : ProcStructLock = param->ProcStructLock;
1001 : : ProcGlobal = param->ProcGlobal;
1002 : : AuxiliaryProcs = param->AuxiliaryProcs;
1003 : : PreparedXactProcs = param->PreparedXactProcs;
1004 : : PMSignalState = param->PMSignalState;
1005 : : ProcSignal = param->ProcSignal;
1006 : :
1007 : : PostmasterPid = param->PostmasterPid;
1008 : : PgStartTime = param->PgStartTime;
1009 : : PgReloadTime = param->PgReloadTime;
1010 : : first_syslogger_file_time = param->first_syslogger_file_time;
1011 : :
1012 : : redirection_done = param->redirection_done;
1013 : : IsBinaryUpgrade = param->IsBinaryUpgrade;
1014 : : query_id_enabled = param->query_id_enabled;
1015 : : max_safe_fds = param->max_safe_fds;
1016 : :
1017 : : MaxBackends = param->MaxBackends;
1018 : : num_pmchild_slots = param->num_pmchild_slots;
1019 : :
1020 : : #ifdef WIN32
1021 : : PostmasterHandle = param->PostmasterHandle;
1022 : : pgwin32_initial_signal_pipe = param->initial_signal_pipe;
1023 : : #else
1024 : : memcpy(&postmaster_alive_fds, ¶m->postmaster_alive_fds,
1025 : : sizeof(postmaster_alive_fds));
1026 : : #endif
1027 : :
1028 : : memcpy(&syslogPipe, ¶m->syslogPipe, sizeof(syslogPipe));
1029 : :
1030 : : strlcpy(my_exec_path, param->my_exec_path, MAXPGPATH);
1031 : :
1032 : : strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
1033 : :
1034 : : /*
1035 : : * We need to restore fd.c's counts of externally-opened FDs; to avoid
1036 : : * confusion, be sure to do this after restoring max_safe_fds. (Note:
1037 : : * BackendInitialize will handle this for (*client_sock)->sock.)
1038 : : */
1039 : : #ifndef WIN32
1040 : : if (postmaster_alive_fds[0] >= 0)
1041 : : ReserveExternalFD();
1042 : : if (postmaster_alive_fds[1] >= 0)
1043 : : ReserveExternalFD();
1044 : : #endif
1045 : : }
1046 : :
1047 : : #endif /* EXEC_BACKEND */
|