PostgreSQL Source Code git master
Loading...
Searching...
No Matches
launch_backend.c
Go to the documentation of this file.
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"
40#include "postmaster/bgwriter.h"
42#include "postmaster/pgarch.h"
44#include "postmaster/startup.h"
50#include "storage/dsm.h"
51#include "storage/io_worker.h"
52#include "storage/pg_shmem.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"
73
74/* Type for a socket that can be inherited to a client process */
75#ifdef WIN32
76typedef struct
77{
78 SOCKET origsocket; /* Original socket value, or PGINVALID_SOCKET
79 * if not a socket */
82#else
83typedef int InheritableSocket;
84#endif
85
86/*
87 * Structure contains all variables passed to exec:ed backends
88 */
89typedef struct
90{
91 char DataDir[MAXPGPATH];
92#ifndef WIN32
93 unsigned long UsedShmemSegID;
94#else
97#endif
98 void *UsedShmemSegAddr;
99#ifdef USE_INJECTION_POINTS
101#endif
104 char **LWLockTrancheNames;
105 int *LWLockCounter;
111 volatile PMSignalData *PMSignalState;
117 bool redirection_done;
118 bool IsBinaryUpgrade;
119 bool query_id_enabled;
120 int max_safe_fds;
121 int MaxBackends;
123#ifdef WIN32
127#else
129 int syslogPipe[2];
130#endif
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 */
144
145 /*
146 * Extra startup data, content depends on the child process.
147 */
148 size_t startup_data_len;
151
152#define SizeOfBackendParameters(startup_data_len) (offsetof(BackendParameters, startup_data) + startup_data_len)
153
154static void read_backend_variables(char *id, void **startup_data, size_t *startup_data_len);
156
157static bool save_backend_variables(BackendParameters *param, int child_slot,
161#endif
162 const void *startup_data, size_t startup_data_len);
163
164static pid_t internal_forkexec(BackendType child_kind, int child_slot,
165 const void *startup_data, size_t startup_data_len,
167
168#endif /* EXEC_BACKEND */
169
170/*
171 * Information needed to launch different kinds of child processes.
172 */
173typedef struct
174{
175 const char *name;
176 void (*main_fn) (const void *startup_data, size_t startup_data_len);
179
181#define PG_PROCTYPE(bktype, description, main_func, shmem_attach) \
182 [bktype] = {description, main_func, shmem_attach},
184#undef PG_PROCTYPE
185};
186
187const char *
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 */
205pid_t
207 void *startup_data, size_t startup_data_len,
209{
210 pid_t pid;
211
213
214 /* Capture time Postmaster initiates process creation for logging */
217
218#ifdef EXEC_BACKEND
219 pid = internal_forkexec(child_type, child_slot,
221 /* the child process will arrive in SubPostmasterMain */
222#else /* !EXEC_BACKEND */
223 pid = fork_process();
224 if (pid == 0) /* child */
225 {
227
228 /* Capture and transfer timings that may be needed for logging */
230 {
232 ((BackendStartupData *) startup_data)->socket_created;
234 ((BackendStartupData *) startup_data)->fork_started;
236 }
237
238 /* Close the postmaster's sockets */
240
241 /* Detangle from postmaster */
243
244 /* Detach shared memory if not needed. */
245 if (!child_process_kinds[child_type].shmem_attach)
246 {
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 */
258
259 MyPMChildSlot = child_slot;
260 if (client_sock)
261 {
264 }
265
266 /*
267 * Run the appropriate Main function
268 */
270 pg_unreachable(); /* main_fn never returns */
271 }
272#endif /* EXEC_BACKEND */
273 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 */
285static pid_t
288{
289 static unsigned long tmpBackendFileNum = 0;
290 pid_t pid;
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 */
306 param = palloc0(paramsz);
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",
317
318 /* Open file */
320 if (!fp)
321 {
322 /*
323 * As in OpenTemporaryFileInTablespace, try to make the temp-file
324 * directory, ignoring errors.
325 */
327
329 if (!fp)
330 {
331 ereport(LOG,
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,
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,
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",
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 */
395static pid_t
398{
399 int retry_count = 0;
402 char cmdLine[MAXPGPATH * 2];
404 BackendParameters *param;
406 size_t paramsz;
407 char paramHandleStr[32];
408 int l;
409
411
412 /* Resume here if we need to retry */
413retry:
414
415 /* Set up shared memory for parameter passing */
416 ZeroMemory(&sa, sizeof(sa));
417 sa.nLength = sizeof(sa);
418 sa.bInheritHandle = TRUE;
420 &sa,
422 0,
423 paramsz,
424 NULL);
426 {
427 ereport(LOG,
428 (errmsg("could not create backend parameter file mapping: error code %lu",
429 GetLastError())));
430 return -1;
431 }
433 if (!param)
434 {
435 ereport(LOG,
436 (errmsg("could not map backend parameter memory: error code %lu",
437 GetLastError())));
439 return -1;
440 }
441
442 /* Format the cmd line */
443#ifdef _WIN64
445#else
447#endif
448 l = snprintf(cmdLine, sizeof(cmdLine) - 1, "\"%s\" --forkchild=%d %s",
450 if (l >= sizeof(cmdLine))
451 {
452 ereport(LOG,
453 (errmsg("subprocess command line too long")));
454 UnmapViewOfFile(param);
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 */
468 NULL, NULL, &si, &pi))
469 {
470 ereport(LOG,
471 (errmsg("CreateProcess() call failed: %m (error code %lu)",
472 GetLastError())));
473 UnmapViewOfFile(param);
475 return -1;
476 }
477
478 if (!save_backend_variables(param, child_slot, client_sock,
479 pi.hProcess, pi.dwProcessId,
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);
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())));
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 */
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 */
576void
577SubPostmasterMain(int argc, char *argv[])
578{
579 void *startup_data;
580 size_t startup_data_len;
581 char *child_kind;
583 TimestampTz fork_end;
584
585 /* In EXEC_BACKEND case we will not have inherited these settings */
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) */
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;
611 elog(ERROR, "unknown child kind %s", child_kind);
613
614 /* Read in the variables file */
616
617 /* Close the postmaster's sockets (as soon as we know them) */
619
620 /* Setup as postmaster child */
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)
641 else
643
644 /* Read in remaining GUC variables */
646
647 /* Capture and transfer timings that may be needed for log_connections */
649 {
651 ((BackendStartupData *) startup_data)->socket_created;
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 */
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 */
678
679 /* Restore basic shared memory pointers */
680 if (UsedShmemSegAddr != NULL)
682
683 /*
684 * Run the appropriate Main function
685 */
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
694static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
697static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
698#endif
699
700
701/* Save critical backend variables into the BackendParameters struct */
702static bool
704 int child_slot, ClientSocket *client_sock,
707#endif
708 const void *startup_data, size_t startup_data_len)
709{
710 if (client_sock)
711 memcpy(&param->client_sock, client_sock, sizeof(ClientSocket));
712 else
713 memset(&param->client_sock, 0, sizeof(ClientSocket));
714 if (!write_inheritable_socket(&param->inh_sock,
716 childPid))
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(&param->initial_signal_pipe,
763 return false;
764#else
765 memcpy(&param->postmaster_alive_fds, &postmaster_alive_fds,
766 sizeof(postmaster_alive_fds));
767#endif
768
769 memcpy(&param->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 */
787static bool
789{
791
793 src,
795 &hChild,
796 0,
797 TRUE,
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 */
817static bool
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 */
838static void
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 */
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",
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
875static void
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(&param, 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 {
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
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 */
924
925#ifdef _WIN64
926 paramHandle = (HANDLE) _atoi64(id);
927#else
928 paramHandle = (HANDLE) atol(id);
929#endif
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(&param, 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
949
951 {
952 write_stderr("could not unmap view of backend variables: error code %lu\n",
953 GetLastError());
954 exit(1);
955 }
956
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
966}
967
968/* Restore critical backend variables from the BackendParameters struct */
969static void
971{
972 if (param->client_sock.sock != PGINVALID_SOCKET)
973 {
975 memcpy(MyClientSocket, &param->client_sock, sizeof(ClientSocket));
976 read_inheritable_socket(&MyClientSocket->sock, &param->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, &param->postmaster_alive_fds,
1023 sizeof(postmaster_alive_fds));
1024#endif
1025
1026 memcpy(&syslogPipe, &param->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)
1040 if (postmaster_alive_fds[1] >= 0)
1042#endif
1043}
1044
1045#endif /* EXEC_BACKEND */
TimestampTz PgReloadTime
Definition timestamp.c:57
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1645
TimestampTz PgStartTime
Definition timestamp.c:54
ConnectionTiming conn_timing
#define write_stderr(str)
Definition parallel.c:186
#define PG_BINARY_R
Definition c.h:1289
#define Assert(condition)
Definition c.h:873
#define FLEXIBLE_ARRAY_MEMBER
Definition c.h:480
#define pg_unreachable()
Definition c.h:341
#define PG_BINARY_W
Definition c.h:1290
int64 TimestampTz
Definition timestamp.h:39
@ DestNone
Definition dest.h:87
void dsm_detach_all(void)
Definition dsm.c:775
int errmsg_internal(const char *fmt,...)
Definition elog.c:1170
int errcode_for_file_access(void)
Definition elog.c:886
int errhint(const char *fmt,...)
Definition elog.c:1330
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define LOG
Definition elog.h:31
#define FATAL
Definition elog.h:41
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
int MakePGDirectory(const char *directoryName)
Definition fd.c:3962
int max_safe_fds
Definition fd.c:159
int FreeFile(FILE *file)
Definition fd.c:2826
void ReserveExternalFD(void)
Definition fd.c:1206
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2627
#define palloc_object(type)
Definition fe_memutils.h:74
#define PG_TEMP_FILES_DIR
Definition file_utils.h:63
#define PG_TEMP_FILE_PREFIX
Definition file_utils.h:64
pid_t fork_process(void)
struct ClientSocket * MyClientSocket
Definition globals.c:50
bool IsBinaryUpgrade
Definition globals.c:121
int MyPMChildSlot
Definition globals.c:54
pid_t PostmasterPid
Definition globals.c:106
int MyProcPid
Definition globals.c:47
char pkglib_path[MAXPGPATH]
Definition globals.c:82
bool IsUnderPostmaster
Definition globals.c:120
int MaxBackends
Definition globals.c:146
char * DataDir
Definition globals.c:71
bool IsPostmasterEnvironment
Definition globals.c:119
char my_exec_path[MAXPGPATH]
Definition globals.c:81
void InitializeGUCOptions(void)
Definition guc.c:1407
#define false
static child_process_kind child_process_kinds[]
const char * PostmasterChildName(BackendType child_type)
pid_t postmaster_child_launch(BackendType child_type, int child_slot, void *startup_data, size_t startup_data_len, ClientSocket *client_sock)
char ** LWLockTrancheNames
Definition lwlock.c:154
int NamedLWLockTrancheRequests
Definition lwlock.c:192
NamedLWLockTrancheRequest * NamedLWLockTrancheRequestArray
Definition lwlock.c:193
LWLockPadded * MainLWLockArray
Definition lwlock.c:161
int * LWLockCounter
Definition lwlock.c:199
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc0(Size size)
Definition mcxt.c:1417
MemoryContext TopMemoryContext
Definition mcxt.c:166
void * palloc(Size size)
Definition mcxt.c:1387
#define IsExternalConnectionBackend(backend_type)
Definition miscadmin.h:405
#define BACKEND_NUM_TYPES
Definition miscadmin.h:377
BackendType
Definition miscadmin.h:338
@ B_LOGGER
Definition miscadmin.h:374
void InitPostmasterChild(void)
Definition miscinit.c:96
void process_shared_preload_libraries(void)
Definition miscinit.c:1851
void checkDataDir(void)
Definition miscinit.c:296
BackendType MyBackendType
Definition miscinit.c:64
void SetDataDir(const char *dir)
Definition miscinit.c:389
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
#define MAXPGPATH
int64 pg_time_t
Definition pgtime.h:23
NON_EXEC_STATIC int num_pmchild_slots
Definition pmchild.c:55
NON_EXEC_STATIC volatile PMSignalData * PMSignalState
Definition pmsignal.c:84
#define sprintf
Definition port.h:262
#define snprintf
Definition port.h:260
#define PGINVALID_SOCKET
Definition port.h:31
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
#define closesocket
Definition port.h:397
CommandDest whereToSendOutput
Definition postgres.c:92
bool redirection_done
Definition postmaster.c:375
int postmaster_alive_fds[2]
Definition postmaster.c:483
void ClosePostmasterPorts(bool am_syslogger)
static int fb(int x)
NON_EXEC_STATIC ProcSignalHeader * ProcSignal
Definition procsignal.c:105
bool query_id_enabled
void InitShmemAllocator(PGShmemHeader *seghdr)
Definition shmem.c:122
HANDLE pgwin32_create_signal_listener(pid_t pid)
Definition signal.c:227
HANDLE pgwin32_initial_signal_pipe
Definition signal.c:28
PGPROC * PreparedXactProcs
Definition proc.c:81
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition proc.c:80
PROC_HDR * ProcGlobal
Definition proc.c:79
NON_EXEC_STATIC slock_t * ProcStructLock
Definition proc.c:76
pgsocket sock
Definition libpq-be.h:250
TimestampTz socket_create
TimestampTz fork_start
Definition proc.h:180
void(* main_fn)(const void *startup_data, size_t startup_data_len)
NON_EXEC_STATIC pg_time_t first_syslogger_file_time
Definition syslogger.c:87
int syslogPipe[2]
Definition syslogger.c:114
void PGSharedMemoryDetach(void)
Definition sysv_shmem.c:972
unsigned long UsedShmemSegID
Definition sysv_shmem.c:95
void * UsedShmemSegAddr
Definition sysv_shmem.c:96
void PGSharedMemoryReAttach(void)
void * ShmemProtectiveRegion
Definition win32_shmem.c:42
int pgwin32_ReserveSharedMemoryRegion(HANDLE hChild)
void PGSharedMemoryNoReAttach(void)
void LocalProcessControlFile(bool reset)
Definition xlog.c:4939