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