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

Generated by: LCOV version 1.16