LCOV - code coverage report
Current view: top level - src/backend/postmaster - launch_backend.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 96.3 % 27 26
Test Date: 2026-03-11 19:16:03 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * launch_backend.c
       4              :  *    Functions for launching backends and other postmaster child
       5              :  *    processes.
       6              :  *
       7              :  * On Unix systems, a new child process is launched with fork().  It inherits
       8              :  * all the global variables and data structures that had been initialized in
       9              :  * the postmaster.  After forking, the child process closes the file
      10              :  * descriptors that are not needed in the child process, and sets up the
      11              :  * mechanism to detect death of the parent postmaster process, etc.  After
      12              :  * that, it calls the right Main function depending on the kind of child
      13              :  * process.
      14              :  *
      15              :  * In EXEC_BACKEND mode, which is used on Windows but can be enabled on other
      16              :  * platforms for testing, the child process is launched by fork() + exec() (or
      17              :  * CreateProcess() on Windows).  It does not inherit the state from the
      18              :  * postmaster, so it needs to re-attach to the shared memory, re-initialize
      19              :  * global variables, reload the config file etc. to get the process to the
      20              :  * same state as after fork() on a Unix system.
      21              :  *
      22              :  *
      23              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      24              :  * Portions Copyright (c) 1994, Regents of the University of California
      25              :  *
      26              :  * IDENTIFICATION
      27              :  *    src/backend/postmaster/launch_backend.c
      28              :  *
      29              :  *-------------------------------------------------------------------------
      30              :  */
      31              : 
      32              : #include "postgres.h"
      33              : 
      34              : #include <unistd.h>
      35              : 
      36              : #include "libpq/libpq-be.h"
      37              : #include "miscadmin.h"
      38              : #include "postmaster/autovacuum.h"
      39              : #include "postmaster/bgworker_internals.h"
      40              : #include "postmaster/bgwriter.h"
      41              : #include "postmaster/fork_process.h"
      42              : #include "postmaster/pgarch.h"
      43              : #include "postmaster/postmaster.h"
      44              : #include "postmaster/startup.h"
      45              : #include "postmaster/syslogger.h"
      46              : #include "postmaster/walsummarizer.h"
      47              : #include "postmaster/walwriter.h"
      48              : #include "replication/slotsync.h"
      49              : #include "replication/walreceiver.h"
      50              : #include "storage/dsm.h"
      51              : #include "storage/io_worker.h"
      52              : #include "storage/pg_shmem.h"
      53              : #include "tcop/backend_startup.h"
      54              : #include "utils/memutils.h"
      55              : 
      56              : #ifdef EXEC_BACKEND
      57              : #include "nodes/queryjumble.h"
      58              : #include "storage/pg_shmem.h"
      59              : #include "storage/spin.h"
      60              : #endif
      61              : 
      62              : 
      63              : #ifdef EXEC_BACKEND
      64              : 
      65              : #include "common/file_utils.h"
      66              : #include "storage/fd.h"
      67              : #include "storage/lwlock.h"
      68              : #include "storage/pmsignal.h"
      69              : #include "storage/proc.h"
      70              : #include "storage/procsignal.h"
      71              : #include "tcop/tcopprot.h"
      72              : #include "utils/injection_point.h"
      73              : 
      74              : /* Type for a socket that can be inherited to a client process */
      75              : #ifdef WIN32
      76              : typedef struct
      77              : {
      78              :     SOCKET      origsocket;     /* Original socket value, or PGINVALID_SOCKET
      79              :                                  * if not a socket */
      80              :     WSAPROTOCOL_INFO wsainfo;
      81              : } InheritableSocket;
      82              : #else
      83              : typedef int InheritableSocket;
      84              : #endif
      85              : 
      86              : /*
      87              :  * Structure contains all variables passed to exec:ed backends
      88              :  */
      89              : typedef struct
      90              : {
      91              :     char        DataDir[MAXPGPATH];
      92              : #ifndef WIN32
      93              :     unsigned long UsedShmemSegID;
      94              : #else
      95              :     void       *ShmemProtectiveRegion;
      96              :     HANDLE      UsedShmemSegID;
      97              : #endif
      98              :     void       *UsedShmemSegAddr;
      99              : #ifdef USE_INJECTION_POINTS
     100              :     struct InjectionPointsCtl *ActiveInjectionPoints;
     101              : #endif
     102              :     int         NamedLWLockTrancheRequests;
     103              :     NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray;
     104              :     char      **LWLockTrancheNames;
     105              :     int        *LWLockCounter;
     106              :     LWLockPadded *MainLWLockArray;
     107              :     PROC_HDR   *ProcGlobal;
     108              :     PGPROC     *AuxiliaryProcs;
     109              :     PGPROC     *PreparedXactProcs;
     110              :     volatile PMSignalData *PMSignalState;
     111              :     ProcSignalHeader *ProcSignal;
     112              :     pid_t       PostmasterPid;
     113              :     TimestampTz PgStartTime;
     114              :     TimestampTz PgReloadTime;
     115              :     pg_time_t   first_syslogger_file_time;
     116              :     bool        redirection_done;
     117              :     bool        IsBinaryUpgrade;
     118              :     bool        query_id_enabled;
     119              :     int         max_safe_fds;
     120              :     int         MaxBackends;
     121              :     int         num_pmchild_slots;
     122              : #ifdef WIN32
     123              :     HANDLE      PostmasterHandle;
     124              :     HANDLE      initial_signal_pipe;
     125              :     HANDLE      syslogPipe[2];
     126              : #else
     127              :     int         postmaster_alive_fds[2];
     128              :     int         syslogPipe[2];
     129              : #endif
     130              :     char        my_exec_path[MAXPGPATH];
     131              :     char        pkglib_path[MAXPGPATH];
     132              : 
     133              :     int         MyPMChildSlot;
     134              : 
     135              :     /*
     136              :      * These are only used by backend processes, but are here because passing
     137              :      * a socket needs some special handling on Windows. 'client_sock' is an
     138              :      * explicit argument to postmaster_child_launch, but is stored in
     139              :      * MyClientSocket in the child process.
     140              :      */
     141              :     ClientSocket client_sock;
     142              :     InheritableSocket inh_sock;
     143              : 
     144              :     /*
     145              :      * Extra startup data, content depends on the child process.
     146              :      */
     147              :     size_t      startup_data_len;
     148              :     char        startup_data[FLEXIBLE_ARRAY_MEMBER];
     149              : } BackendParameters;
     150              : 
     151              : #define SizeOfBackendParameters(startup_data_len) (offsetof(BackendParameters, startup_data) + startup_data_len)
     152              : 
     153              : static void read_backend_variables(char *id, void **startup_data, size_t *startup_data_len);
     154              : static void restore_backend_variables(BackendParameters *param);
     155              : 
     156              : static bool save_backend_variables(BackendParameters *param, int child_slot,
     157              :                                    const ClientSocket *client_sock,
     158              : #ifdef WIN32
     159              :                                    HANDLE childProcess, pid_t childPid,
     160              : #endif
     161              :                                    const void *startup_data, size_t startup_data_len);
     162              : 
     163              : static pid_t internal_forkexec(BackendType child_kind, int child_slot,
     164              :                                const void *startup_data, size_t startup_data_len,
     165              :                                const 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) (const void *startup_data, size_t startup_data_len);
     176              :     bool        shmem_attach;
     177              : } child_process_kind;
     178              : 
     179              : static child_process_kind child_process_kinds[] = {
     180              : #define PG_PROCTYPE(bktype, bkcategory, description, main_func, shmem_attach) \
     181              :     [bktype] = {description, main_func, shmem_attach},
     182              : #include "postmaster/proctypelist.h"
     183              : #undef PG_PROCTYPE
     184              : };
     185              : 
     186              : const char *
     187         1033 : PostmasterChildName(BackendType child_type)
     188              : {
     189         1033 :     return child_process_kinds[child_type].name;
     190              : }
     191              : 
     192              : /*
     193              :  * Start a new postmaster child process.
     194              :  *
     195              :  * The child process will be restored to roughly the same state whether
     196              :  * EXEC_BACKEND is used or not: it will be attached to shared memory if
     197              :  * appropriate, and fds and other resources that we've inherited from
     198              :  * postmaster that are not needed in a child process have been closed.
     199              :  *
     200              :  * 'child_slot' is the PMChildFlags array index reserved for the child
     201              :  * process.  'startup_data' is an optional contiguous chunk of data that is
     202              :  * passed to the child process.
     203              :  */
     204              : pid_t
     205        26473 : postmaster_child_launch(BackendType child_type, int child_slot,
     206              :                         void *startup_data, size_t startup_data_len,
     207              :                         const ClientSocket *client_sock)
     208              : {
     209              :     pid_t       pid;
     210              : 
     211              :     Assert(IsPostmasterEnvironment && !IsUnderPostmaster);
     212              : 
     213              :     /* Capture time Postmaster initiates process creation for logging */
     214        26473 :     if (IsExternalConnectionBackend(child_type))
     215        14097 :         ((BackendStartupData *) startup_data)->fork_started = GetCurrentTimestamp();
     216              : 
     217              : #ifdef EXEC_BACKEND
     218              :     pid = internal_forkexec(child_type, child_slot,
     219              :                             startup_data, startup_data_len, client_sock);
     220              :     /* the child process will arrive in SubPostmasterMain */
     221              : #else                           /* !EXEC_BACKEND */
     222        26473 :     pid = fork_process();
     223        50000 :     if (pid == 0)               /* child */
     224              :     {
     225        23527 :         MyBackendType = child_type;
     226              : 
     227              :         /* Capture and transfer timings that may be needed for logging */
     228        23527 :         if (IsExternalConnectionBackend(child_type))
     229              :         {
     230        13919 :             conn_timing.socket_create =
     231        13919 :                 ((BackendStartupData *) startup_data)->socket_created;
     232        13919 :             conn_timing.fork_start =
     233        13919 :                 ((BackendStartupData *) startup_data)->fork_started;
     234        13919 :             conn_timing.fork_end = GetCurrentTimestamp();
     235              :         }
     236              : 
     237              :         /* Close the postmaster's sockets */
     238        23527 :         ClosePostmasterPorts(child_type == B_LOGGER);
     239              : 
     240              :         /* Detangle from postmaster */
     241        23527 :         InitPostmasterChild();
     242              : 
     243              :         /* Detach shared memory if not needed. */
     244        23527 :         if (!child_process_kinds[child_type].shmem_attach)
     245              :         {
     246            1 :             dsm_detach_all();
     247            1 :             PGSharedMemoryDetach();
     248              :         }
     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        23527 :         MemoryContextSwitchTo(TopMemoryContext);
     257              : 
     258        23527 :         MyPMChildSlot = child_slot;
     259        23527 :         if (client_sock)
     260              :         {
     261        14118 :             MyClientSocket = palloc_object(ClientSocket);
     262        14118 :             memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
     263              :         }
     264              : 
     265              :         /*
     266              :          * Run the appropriate Main function
     267              :          */
     268        23527 :         child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
     269            0 :         pg_unreachable();       /* main_fn never returns */
     270              :     }
     271              : #endif                          /* EXEC_BACKEND */
     272        26473 :     return pid;
     273              : }
     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, const 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, const 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              :     MyBackendType = child_type;
     612              : 
     613              :     /* Read in the variables file */
     614              :     read_backend_variables(argv[2], &startup_data, &startup_data_len);
     615              : 
     616              :     /* Close the postmaster's sockets (as soon as we know them) */
     617              :     ClosePostmasterPorts(child_type == B_LOGGER);
     618              : 
     619              :     /* Setup as postmaster child */
     620              :     InitPostmasterChild();
     621              : 
     622              :     /*
     623              :      * If appropriate, physically re-attach to shared memory segment. We want
     624              :      * to do this before going any further to ensure that we can attach at the
     625              :      * same address the postmaster used.  On the other hand, if we choose not
     626              :      * to re-attach, we may have other cleanup to do.
     627              :      *
     628              :      * If testing EXEC_BACKEND on Linux, you should run this as root before
     629              :      * starting the postmaster:
     630              :      *
     631              :      * sysctl -w kernel.randomize_va_space=0
     632              :      *
     633              :      * This prevents using randomized stack and code addresses that cause the
     634              :      * child process's memory map to be different from the parent's, making it
     635              :      * sometimes impossible to attach to shared memory at the desired address.
     636              :      * Return the setting to its old value (usually '1' or '2') when finished.
     637              :      */
     638              :     if (child_process_kinds[child_type].shmem_attach)
     639              :         PGSharedMemoryReAttach();
     640              :     else
     641              :         PGSharedMemoryNoReAttach();
     642              : 
     643              :     /* Read in remaining GUC variables */
     644              :     read_nondefault_variables();
     645              : 
     646              :     /* Capture and transfer timings that may be needed for log_connections */
     647              :     if (IsExternalConnectionBackend(child_type))
     648              :     {
     649              :         conn_timing.socket_create =
     650              :             ((BackendStartupData *) startup_data)->socket_created;
     651              :         conn_timing.fork_start =
     652              :             ((BackendStartupData *) startup_data)->fork_started;
     653              :         conn_timing.fork_end = fork_end;
     654              :     }
     655              : 
     656              :     /*
     657              :      * Check that the data directory looks valid, which will also check the
     658              :      * privileges on the data directory and update our umask and file/group
     659              :      * variables for creating files later.  Note: this should really be done
     660              :      * before we create any files or directories.
     661              :      */
     662              :     checkDataDir();
     663              : 
     664              :     /*
     665              :      * (re-)read control file, as it contains config. The postmaster will
     666              :      * already have read this, but this process doesn't know about that.
     667              :      */
     668              :     LocalProcessControlFile(false);
     669              : 
     670              :     /*
     671              :      * Reload any libraries that were preloaded by the postmaster.  Since we
     672              :      * exec'd this process, those libraries didn't come along with us; but we
     673              :      * should load them into all child processes to be consistent with the
     674              :      * non-EXEC_BACKEND behavior.
     675              :      */
     676              :     process_shared_preload_libraries();
     677              : 
     678              :     /* Restore basic shared memory pointers */
     679              :     if (UsedShmemSegAddr != NULL)
     680              :         InitShmemAllocator(UsedShmemSegAddr);
     681              : 
     682              :     /*
     683              :      * Run the appropriate Main function
     684              :      */
     685              :     child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
     686              :     pg_unreachable();           /* main_fn never returns */
     687              : }
     688              : 
     689              : #ifndef WIN32
     690              : #define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
     691              : #define read_inheritable_socket(dest, src) (*(dest) = *(src))
     692              : #else
     693              : static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
     694              : static bool write_inheritable_socket(InheritableSocket *dest, SOCKET src,
     695              :                                      pid_t childPid);
     696              : static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
     697              : #endif
     698              : 
     699              : 
     700              : /* Save critical backend variables into the BackendParameters struct */
     701              : static bool
     702              : save_backend_variables(BackendParameters *param,
     703              :                        int child_slot, const ClientSocket *client_sock,
     704              : #ifdef WIN32
     705              :                        HANDLE childProcess, pid_t childPid,
     706              : #endif
     707              :                        const void *startup_data, size_t startup_data_len)
     708              : {
     709              :     if (client_sock)
     710              :         memcpy(&param->client_sock, client_sock, sizeof(ClientSocket));
     711              :     else
     712              :         memset(&param->client_sock, 0, sizeof(ClientSocket));
     713              :     if (!write_inheritable_socket(&param->inh_sock,
     714              :                                   client_sock ? client_sock->sock : PGINVALID_SOCKET,
     715              :                                   childPid))
     716              :         return false;
     717              : 
     718              :     strlcpy(param->DataDir, DataDir, MAXPGPATH);
     719              : 
     720              :     param->MyPMChildSlot = child_slot;
     721              : 
     722              : #ifdef WIN32
     723              :     param->ShmemProtectiveRegion = ShmemProtectiveRegion;
     724              : #endif
     725              :     param->UsedShmemSegID = UsedShmemSegID;
     726              :     param->UsedShmemSegAddr = UsedShmemSegAddr;
     727              : 
     728              : #ifdef USE_INJECTION_POINTS
     729              :     param->ActiveInjectionPoints = ActiveInjectionPoints;
     730              : #endif
     731              : 
     732              :     param->NamedLWLockTrancheRequests = NamedLWLockTrancheRequests;
     733              :     param->NamedLWLockTrancheRequestArray = NamedLWLockTrancheRequestArray;
     734              :     param->LWLockTrancheNames = LWLockTrancheNames;
     735              :     param->LWLockCounter = LWLockCounter;
     736              :     param->MainLWLockArray = MainLWLockArray;
     737              :     param->ProcGlobal = ProcGlobal;
     738              :     param->AuxiliaryProcs = AuxiliaryProcs;
     739              :     param->PreparedXactProcs = PreparedXactProcs;
     740              :     param->PMSignalState = PMSignalState;
     741              :     param->ProcSignal = ProcSignal;
     742              : 
     743              :     param->PostmasterPid = PostmasterPid;
     744              :     param->PgStartTime = PgStartTime;
     745              :     param->PgReloadTime = PgReloadTime;
     746              :     param->first_syslogger_file_time = first_syslogger_file_time;
     747              : 
     748              :     param->redirection_done = redirection_done;
     749              :     param->IsBinaryUpgrade = IsBinaryUpgrade;
     750              :     param->query_id_enabled = query_id_enabled;
     751              :     param->max_safe_fds = max_safe_fds;
     752              : 
     753              :     param->MaxBackends = MaxBackends;
     754              :     param->num_pmchild_slots = num_pmchild_slots;
     755              : 
     756              : #ifdef WIN32
     757              :     param->PostmasterHandle = PostmasterHandle;
     758              :     if (!write_duplicated_handle(&param->initial_signal_pipe,
     759              :                                  pgwin32_create_signal_listener(childPid),
     760              :                                  childProcess))
     761              :         return false;
     762              : #else
     763              :     memcpy(&param->postmaster_alive_fds, &postmaster_alive_fds,
     764              :            sizeof(postmaster_alive_fds));
     765              : #endif
     766              : 
     767              :     memcpy(&param->syslogPipe, &syslogPipe, sizeof(syslogPipe));
     768              : 
     769              :     strlcpy(param->my_exec_path, my_exec_path, MAXPGPATH);
     770              : 
     771              :     strlcpy(param->pkglib_path, pkglib_path, MAXPGPATH);
     772              : 
     773              :     param->startup_data_len = startup_data_len;
     774              :     if (startup_data_len > 0)
     775              :         memcpy(param->startup_data, startup_data, startup_data_len);
     776              : 
     777              :     return true;
     778              : }
     779              : 
     780              : #ifdef WIN32
     781              : /*
     782              :  * Duplicate a handle for usage in a child process, and write the child
     783              :  * process instance of the handle to the parameter file.
     784              :  */
     785              : static bool
     786              : write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE childProcess)
     787              : {
     788              :     HANDLE      hChild = INVALID_HANDLE_VALUE;
     789              : 
     790              :     if (!DuplicateHandle(GetCurrentProcess(),
     791              :                          src,
     792              :                          childProcess,
     793              :                          &hChild,
     794              :                          0,
     795              :                          TRUE,
     796              :                          DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
     797              :     {
     798              :         ereport(LOG,
     799              :                 (errmsg_internal("could not duplicate handle to be written to backend parameter file: error code %lu",
     800              :                                  GetLastError())));
     801              :         return false;
     802              :     }
     803              : 
     804              :     *dest = hChild;
     805              :     return true;
     806              : }
     807              : 
     808              : /*
     809              :  * Duplicate a socket for usage in a child process, and write the resulting
     810              :  * structure to the parameter file.
     811              :  * This is required because a number of LSPs (Layered Service Providers) very
     812              :  * common on Windows (antivirus, firewalls, download managers etc) break
     813              :  * straight socket inheritance.
     814              :  */
     815              : static bool
     816              : write_inheritable_socket(InheritableSocket *dest, SOCKET src, pid_t childpid)
     817              : {
     818              :     dest->origsocket = src;
     819              :     if (src != 0 && src != PGINVALID_SOCKET)
     820              :     {
     821              :         /* Actual socket */
     822              :         if (WSADuplicateSocket(src, childpid, &dest->wsainfo) != 0)
     823              :         {
     824              :             ereport(LOG,
     825              :                     (errmsg("could not duplicate socket %d for use in backend: error code %d",
     826              :                             (int) src, WSAGetLastError())));
     827              :             return false;
     828              :         }
     829              :     }
     830              :     return true;
     831              : }
     832              : 
     833              : /*
     834              :  * Read a duplicate socket structure back, and get the socket descriptor.
     835              :  */
     836              : static void
     837              : read_inheritable_socket(SOCKET *dest, InheritableSocket *src)
     838              : {
     839              :     SOCKET      s;
     840              : 
     841              :     if (src->origsocket == PGINVALID_SOCKET || src->origsocket == 0)
     842              :     {
     843              :         /* Not a real socket! */
     844              :         *dest = src->origsocket;
     845              :     }
     846              :     else
     847              :     {
     848              :         /* Actual socket, so create from structure */
     849              :         s = WSASocket(FROM_PROTOCOL_INFO,
     850              :                       FROM_PROTOCOL_INFO,
     851              :                       FROM_PROTOCOL_INFO,
     852              :                       &src->wsainfo,
     853              :                       0,
     854              :                       0);
     855              :         if (s == INVALID_SOCKET)
     856              :         {
     857              :             write_stderr("could not create inherited socket: error code %d\n",
     858              :                          WSAGetLastError());
     859              :             exit(1);
     860              :         }
     861              :         *dest = s;
     862              : 
     863              :         /*
     864              :          * To make sure we don't get two references to the same socket, close
     865              :          * the original one. (This would happen when inheritance actually
     866              :          * works..
     867              :          */
     868              :         closesocket(src->origsocket);
     869              :     }
     870              : }
     871              : #endif
     872              : 
     873              : static void
     874              : read_backend_variables(char *id, void **startup_data, size_t *startup_data_len)
     875              : {
     876              :     BackendParameters param;
     877              : 
     878              : #ifndef WIN32
     879              :     /* Non-win32 implementation reads from file */
     880              :     FILE       *fp;
     881              : 
     882              :     /* Open file */
     883              :     fp = AllocateFile(id, PG_BINARY_R);
     884              :     if (!fp)
     885              :     {
     886              :         write_stderr("could not open backend variables file \"%s\": %m\n", id);
     887              :         exit(1);
     888              :     }
     889              : 
     890              :     if (fread(&param, sizeof(param), 1, fp) != 1)
     891              :     {
     892              :         write_stderr("could not read from backend variables file \"%s\": %m\n", id);
     893              :         exit(1);
     894              :     }
     895              : 
     896              :     /* read startup data */
     897              :     *startup_data_len = param.startup_data_len;
     898              :     if (param.startup_data_len > 0)
     899              :     {
     900              :         *startup_data = palloc(*startup_data_len);
     901              :         if (fread(*startup_data, *startup_data_len, 1, fp) != 1)
     902              :         {
     903              :             write_stderr("could not read startup data from backend variables file \"%s\": %m\n",
     904              :                          id);
     905              :             exit(1);
     906              :         }
     907              :     }
     908              :     else
     909              :         *startup_data = NULL;
     910              : 
     911              :     /* Release file */
     912              :     FreeFile(fp);
     913              :     if (unlink(id) != 0)
     914              :     {
     915              :         write_stderr("could not remove file \"%s\": %m\n", id);
     916              :         exit(1);
     917              :     }
     918              : #else
     919              :     /* Win32 version uses mapped file */
     920              :     HANDLE      paramHandle;
     921              :     BackendParameters *paramp;
     922              : 
     923              : #ifdef _WIN64
     924              :     paramHandle = (HANDLE) _atoi64(id);
     925              : #else
     926              :     paramHandle = (HANDLE) atol(id);
     927              : #endif
     928              :     paramp = MapViewOfFile(paramHandle, FILE_MAP_READ, 0, 0, 0);
     929              :     if (!paramp)
     930              :     {
     931              :         write_stderr("could not map view of backend variables: error code %lu\n",
     932              :                      GetLastError());
     933              :         exit(1);
     934              :     }
     935              : 
     936              :     memcpy(&param, paramp, sizeof(BackendParameters));
     937              : 
     938              :     /* read startup data */
     939              :     *startup_data_len = param.startup_data_len;
     940              :     if (param.startup_data_len > 0)
     941              :     {
     942              :         *startup_data = palloc(paramp->startup_data_len);
     943              :         memcpy(*startup_data, paramp->startup_data, param.startup_data_len);
     944              :     }
     945              :     else
     946              :         *startup_data = NULL;
     947              : 
     948              :     if (!UnmapViewOfFile(paramp))
     949              :     {
     950              :         write_stderr("could not unmap view of backend variables: error code %lu\n",
     951              :                      GetLastError());
     952              :         exit(1);
     953              :     }
     954              : 
     955              :     if (!CloseHandle(paramHandle))
     956              :     {
     957              :         write_stderr("could not close handle to backend parameter variables: error code %lu\n",
     958              :                      GetLastError());
     959              :         exit(1);
     960              :     }
     961              : #endif
     962              : 
     963              :     restore_backend_variables(&param);
     964              : }
     965              : 
     966              : /* Restore critical backend variables from the BackendParameters struct */
     967              : static void
     968              : restore_backend_variables(BackendParameters *param)
     969              : {
     970              :     if (param->client_sock.sock != PGINVALID_SOCKET)
     971              :     {
     972              :         MyClientSocket = MemoryContextAlloc(TopMemoryContext, sizeof(ClientSocket));
     973              :         memcpy(MyClientSocket, &param->client_sock, sizeof(ClientSocket));
     974              :         read_inheritable_socket(&MyClientSocket->sock, &param->inh_sock);
     975              :     }
     976              : 
     977              :     SetDataDir(param->DataDir);
     978              : 
     979              :     MyPMChildSlot = param->MyPMChildSlot;
     980              : 
     981              : #ifdef WIN32
     982              :     ShmemProtectiveRegion = param->ShmemProtectiveRegion;
     983              : #endif
     984              :     UsedShmemSegID = param->UsedShmemSegID;
     985              :     UsedShmemSegAddr = param->UsedShmemSegAddr;
     986              : 
     987              : #ifdef USE_INJECTION_POINTS
     988              :     ActiveInjectionPoints = param->ActiveInjectionPoints;
     989              : #endif
     990              : 
     991              :     NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests;
     992              :     NamedLWLockTrancheRequestArray = param->NamedLWLockTrancheRequestArray;
     993              :     LWLockTrancheNames = param->LWLockTrancheNames;
     994              :     LWLockCounter = param->LWLockCounter;
     995              :     MainLWLockArray = param->MainLWLockArray;
     996              :     ProcGlobal = param->ProcGlobal;
     997              :     AuxiliaryProcs = param->AuxiliaryProcs;
     998              :     PreparedXactProcs = param->PreparedXactProcs;
     999              :     PMSignalState = param->PMSignalState;
    1000              :     ProcSignal = param->ProcSignal;
    1001              : 
    1002              :     PostmasterPid = param->PostmasterPid;
    1003              :     PgStartTime = param->PgStartTime;
    1004              :     PgReloadTime = param->PgReloadTime;
    1005              :     first_syslogger_file_time = param->first_syslogger_file_time;
    1006              : 
    1007              :     redirection_done = param->redirection_done;
    1008              :     IsBinaryUpgrade = param->IsBinaryUpgrade;
    1009              :     query_id_enabled = param->query_id_enabled;
    1010              :     max_safe_fds = param->max_safe_fds;
    1011              : 
    1012              :     MaxBackends = param->MaxBackends;
    1013              :     num_pmchild_slots = param->num_pmchild_slots;
    1014              : 
    1015              : #ifdef WIN32
    1016              :     PostmasterHandle = param->PostmasterHandle;
    1017              :     pgwin32_initial_signal_pipe = param->initial_signal_pipe;
    1018              : #else
    1019              :     memcpy(&postmaster_alive_fds, &param->postmaster_alive_fds,
    1020              :            sizeof(postmaster_alive_fds));
    1021              : #endif
    1022              : 
    1023              :     memcpy(&syslogPipe, &param->syslogPipe, sizeof(syslogPipe));
    1024              : 
    1025              :     strlcpy(my_exec_path, param->my_exec_path, MAXPGPATH);
    1026              : 
    1027              :     strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
    1028              : 
    1029              :     /*
    1030              :      * We need to restore fd.c's counts of externally-opened FDs; to avoid
    1031              :      * confusion, be sure to do this after restoring max_safe_fds.  (Note:
    1032              :      * BackendInitialize will handle this for (*client_sock)->sock.)
    1033              :      */
    1034              : #ifndef WIN32
    1035              :     if (postmaster_alive_fds[0] >= 0)
    1036              :         ReserveExternalFD();
    1037              :     if (postmaster_alive_fds[1] >= 0)
    1038              :         ReserveExternalFD();
    1039              : #endif
    1040              : }
    1041              : 
    1042              : #endif                          /* EXEC_BACKEND */
        

Generated by: LCOV version 2.0-1