LCOV - code coverage report
Current view: top level - src/backend/postmaster - launch_backend.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 96.3 % 27 26
Test Date: 2026-07-21 09:15:43 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 85.7 % 14 12

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * launch_backend.c
       4                 :             :  *    Functions for launching backends and other postmaster child
       5                 :             :  *    processes.
       6                 :             :  *
       7                 :             :  * On Unix systems, a new child process is launched with fork().  It inherits
       8                 :             :  * all the global variables and data structures that had been initialized in
       9                 :             :  * the postmaster.  After forking, the child process closes the file
      10                 :             :  * descriptors that are not needed in the child process, and sets up the
      11                 :             :  * mechanism to detect death of the parent postmaster process, etc.  After
      12                 :             :  * that, it calls the right Main function depending on the kind of child
      13                 :             :  * process.
      14                 :             :  *
      15                 :             :  * In EXEC_BACKEND mode, which is used on Windows but can be enabled on other
      16                 :             :  * platforms for testing, the child process is launched by fork() + exec() (or
      17                 :             :  * CreateProcess() on Windows).  It does not inherit the state from the
      18                 :             :  * postmaster, so it needs to re-attach to the shared memory, re-initialize
      19                 :             :  * global variables, reload the config file etc. to get the process to the
      20                 :             :  * same state as after fork() on a Unix system.
      21                 :             :  *
      22                 :             :  *
      23                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      24                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      25                 :             :  *
      26                 :             :  * IDENTIFICATION
      27                 :             :  *    src/backend/postmaster/launch_backend.c
      28                 :             :  *
      29                 :             :  *-------------------------------------------------------------------------
      30                 :             :  */
      31                 :             : 
      32                 :             : #include "postgres.h"
      33                 :             : 
      34                 :             : #include <unistd.h>
      35                 :             : 
      36                 :             : #include "libpq/libpq-be.h"
      37                 :             : #include "miscadmin.h"
      38                 :             : #include "postmaster/autovacuum.h"
      39                 :             : #include "postmaster/bgworker_internals.h"
      40                 :             : #include "postmaster/bgwriter.h"
      41                 :             : #include "postmaster/fork_process.h"
      42                 :             : #include "postmaster/pgarch.h"
      43                 :             : #include "postmaster/postmaster.h"
      44                 :             : #include "postmaster/startup.h"
      45                 :             : #include "postmaster/syslogger.h"
      46                 :             : #include "postmaster/walsummarizer.h"
      47                 :             : #include "postmaster/walwriter.h"
      48                 :             : #include "replication/slotsync.h"
      49                 :             : #include "replication/walreceiver.h"
      50                 :             : #include "storage/dsm.h"
      51                 :             : #include "storage/io_worker.h"
      52                 :             : #include "storage/ipc.h"
      53                 :             : #include "storage/pg_shmem.h"
      54                 :             : #include "storage/shmem_internal.h"
      55                 :             : #include "tcop/backend_startup.h"
      56                 :             : #include "utils/memutils.h"
      57                 :             : 
      58                 :             : #ifdef EXEC_BACKEND
      59                 :             : #include "nodes/queryjumble.h"
      60                 :             : #include "portability/instr_time.h"
      61                 :             : #include "storage/pg_shmem.h"
      62                 :             : #include "storage/spin.h"
      63                 :             : #endif
      64                 :             : 
      65                 :             : 
      66                 :             : #ifdef EXEC_BACKEND
      67                 :             : 
      68                 :             : #include "common/file_utils.h"
      69                 :             : #include "storage/fd.h"
      70                 :             : #include "storage/lwlock.h"
      71                 :             : #include "storage/pmsignal.h"
      72                 :             : #include "storage/proc.h"
      73                 :             : #include "storage/procsignal.h"
      74                 :             : #include "tcop/tcopprot.h"
      75                 :             : #include "utils/injection_point.h"
      76                 :             : 
      77                 :             : /* Type for a socket that can be inherited to a client process */
      78                 :             : #ifdef WIN32
      79                 :             : typedef struct
      80                 :             : {
      81                 :             :     SOCKET      origsocket;     /* Original socket value, or PGINVALID_SOCKET
      82                 :             :                                  * if not a socket */
      83                 :             :     WSAPROTOCOL_INFO wsainfo;
      84                 :             : } InheritableSocket;
      85                 :             : #else
      86                 :             : typedef int InheritableSocket;
      87                 :             : #endif
      88                 :             : 
      89                 :             : /*
      90                 :             :  * Structure contains all variables passed to exec:ed backends
      91                 :             :  */
      92                 :             : typedef struct
      93                 :             : {
      94                 :             :     char        DataDir[MAXPGPATH];
      95                 :             : #ifndef WIN32
      96                 :             :     unsigned long UsedShmemSegID;
      97                 :             : #else
      98                 :             :     void       *ShmemProtectiveRegion;
      99                 :             :     HANDLE      UsedShmemSegID;
     100                 :             : #endif
     101                 :             :     void       *UsedShmemSegAddr;
     102                 :             : #ifdef USE_INJECTION_POINTS
     103                 :             :     struct InjectionPointsCtl *ActiveInjectionPoints;
     104                 :             : #endif
     105                 :             :     PROC_HDR   *ProcGlobal;
     106                 :             :     PGPROC     *AuxiliaryProcs;
     107                 :             :     PGPROC     *PreparedXactProcs;
     108                 :             :     volatile PMSignalData *PMSignalState;
     109                 :             :     ProcSignalHeader *ProcSignal;
     110                 :             :     pid_t       PostmasterPid;
     111                 :             :     TimestampTz PgStartTime;
     112                 :             :     TimestampTz PgReloadTime;
     113                 :             :     pg_time_t   first_syslogger_file_time;
     114                 :             :     bool        redirection_done;
     115                 :             :     bool        IsBinaryUpgrade;
     116                 :             :     bool        query_id_enabled;
     117                 :             :     int         max_safe_fds;
     118                 :             :     int         MaxBackends;
     119                 :             :     int         num_pmchild_slots;
     120                 :             : #ifdef WIN32
     121                 :             :     HANDLE      PostmasterHandle;
     122                 :             :     HANDLE      initial_signal_pipe;
     123                 :             :     HANDLE      syslogPipe[2];
     124                 :             : #else
     125                 :             :     int         postmaster_alive_fds[2];
     126                 :             :     int         syslogPipe[2];
     127                 :             : #endif
     128                 :             :     char        my_exec_path[MAXPGPATH];
     129                 :             :     char        pkglib_path[MAXPGPATH];
     130                 :             : 
     131                 :             :     int         MyPMChildSlot;
     132                 :             : 
     133                 :             :     int32       timing_tsc_frequency_khz;
     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                 :        1157 : PostmasterChildName(BackendType child_type)
     188                 :             : {
     189                 :        1157 :     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                 :       27650 : 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   [ +  +  -  + ]:       27650 :     if (IsExternalConnectionBackend(child_type))
     215                 :       15159 :         ((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                 :       27650 :     pid = fork_process();
     223         [ +  + ]:       52594 :     if (pid == 0)               /* child */
     224                 :             :     {
     225                 :       24944 :         MyBackendType = child_type;
     226                 :             : 
     227                 :             :         /* Capture and transfer timings that may be needed for logging */
     228   [ +  +  -  + ]:       24944 :         if (IsExternalConnectionBackend(child_type))
     229                 :             :         {
     230                 :       14968 :             conn_timing.socket_create =
     231                 :       14968 :                 ((BackendStartupData *) startup_data)->socket_created;
     232                 :       14968 :             conn_timing.fork_start =
     233                 :       14968 :                 ((BackendStartupData *) startup_data)->fork_started;
     234                 :       14968 :             conn_timing.fork_end = GetCurrentTimestamp();
     235                 :             :         }
     236                 :             : 
     237                 :             :         /* Close the postmaster's sockets */
     238                 :       24944 :         ClosePostmasterPorts(child_type == B_LOGGER);
     239                 :             : 
     240                 :             :         /* Detangle from postmaster */
     241                 :       24944 :         InitPostmasterChild();
     242                 :             : 
     243                 :             :         /* Detach shared memory if not needed. */
     244         [ +  + ]:       24944 :         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                 :       24944 :         MemoryContextSwitchTo(TopMemoryContext);
     257                 :             : 
     258                 :       24944 :         MyPMChildSlot = child_slot;
     259         [ +  + ]:       24944 :         if (client_sock)
     260                 :             :         {
     261                 :       15195 :             MyClientSocket = palloc_object(ClientSocket);
     262                 :       15195 :             memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
     263                 :             :         }
     264                 :             : 
     265                 :             :         /*
     266                 :             :          * Run the appropriate Main function
     267                 :             :          */
     268                 :       24944 :         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                 :       27650 :     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                 :             :     RegisterBuiltinShmemCallbacks();
     671                 :             : 
     672                 :             :     /*
     673                 :             :      * Reload any libraries that were preloaded by the postmaster.  Since we
     674                 :             :      * exec'd this process, those libraries didn't come along with us; but we
     675                 :             :      * should load them into all child processes to be consistent with the
     676                 :             :      * non-EXEC_BACKEND behavior.
     677                 :             :      */
     678                 :             :     process_shared_preload_libraries();
     679                 :             : 
     680                 :             :     /* Restore basic shared memory pointers */
     681                 :             :     if (UsedShmemSegAddr != NULL)
     682                 :             :     {
     683                 :             :         InitShmemAllocator(UsedShmemSegAddr);
     684                 :             :         ShmemCallRequestCallbacks();
     685                 :             :     }
     686                 :             : 
     687                 :             :     /*
     688                 :             :      * Run the appropriate Main function
     689                 :             :      */
     690                 :             :     child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
     691                 :             :     pg_unreachable();           /* main_fn never returns */
     692                 :             : }
     693                 :             : 
     694                 :             : #ifndef WIN32
     695                 :             : #define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
     696                 :             : #define read_inheritable_socket(dest, src) (*(dest) = *(src))
     697                 :             : #else
     698                 :             : static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
     699                 :             : static bool write_inheritable_socket(InheritableSocket *dest, SOCKET src,
     700                 :             :                                      pid_t childPid);
     701                 :             : static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
     702                 :             : #endif
     703                 :             : 
     704                 :             : 
     705                 :             : /* Save critical backend variables into the BackendParameters struct */
     706                 :             : static bool
     707                 :             : save_backend_variables(BackendParameters *param,
     708                 :             :                        int child_slot, const ClientSocket *client_sock,
     709                 :             : #ifdef WIN32
     710                 :             :                        HANDLE childProcess, pid_t childPid,
     711                 :             : #endif
     712                 :             :                        const void *startup_data, size_t startup_data_len)
     713                 :             : {
     714                 :             :     if (client_sock)
     715                 :             :         memcpy(&param->client_sock, client_sock, sizeof(ClientSocket));
     716                 :             :     else
     717                 :             :         memset(&param->client_sock, 0, sizeof(ClientSocket));
     718                 :             :     if (!write_inheritable_socket(&param->inh_sock,
     719                 :             :                                   client_sock ? client_sock->sock : PGINVALID_SOCKET,
     720                 :             :                                   childPid))
     721                 :             :         return false;
     722                 :             : 
     723                 :             :     strlcpy(param->DataDir, DataDir, MAXPGPATH);
     724                 :             : 
     725                 :             :     param->MyPMChildSlot = child_slot;
     726                 :             : 
     727                 :             : #ifdef WIN32
     728                 :             :     param->ShmemProtectiveRegion = ShmemProtectiveRegion;
     729                 :             : #endif
     730                 :             :     param->UsedShmemSegID = UsedShmemSegID;
     731                 :             :     param->UsedShmemSegAddr = UsedShmemSegAddr;
     732                 :             : 
     733                 :             : #ifdef USE_INJECTION_POINTS
     734                 :             :     param->ActiveInjectionPoints = ActiveInjectionPoints;
     735                 :             : #endif
     736                 :             : 
     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                 :             :     param->timing_tsc_frequency_khz = timing_tsc_frequency_khz;
     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                 :             :     ProcGlobal = param->ProcGlobal;
     994                 :             :     AuxiliaryProcs = param->AuxiliaryProcs;
     995                 :             :     PreparedXactProcs = param->PreparedXactProcs;
     996                 :             :     PMSignalState = param->PMSignalState;
     997                 :             :     ProcSignal = param->ProcSignal;
     998                 :             : 
     999                 :             :     PostmasterPid = param->PostmasterPid;
    1000                 :             :     PgStartTime = param->PgStartTime;
    1001                 :             :     PgReloadTime = param->PgReloadTime;
    1002                 :             :     first_syslogger_file_time = param->first_syslogger_file_time;
    1003                 :             : 
    1004                 :             :     redirection_done = param->redirection_done;
    1005                 :             :     IsBinaryUpgrade = param->IsBinaryUpgrade;
    1006                 :             :     query_id_enabled = param->query_id_enabled;
    1007                 :             :     max_safe_fds = param->max_safe_fds;
    1008                 :             : 
    1009                 :             :     MaxBackends = param->MaxBackends;
    1010                 :             :     num_pmchild_slots = param->num_pmchild_slots;
    1011                 :             : 
    1012                 :             :     timing_tsc_frequency_khz = param->timing_tsc_frequency_khz;
    1013                 :             : 
    1014                 :             :     /* Re-run logic usually done by assign_timing_clock_source */
    1015                 :             :     pg_initialize_timing();
    1016                 :             :     pg_set_timing_clock_source(timing_clock_source);
    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 2.0-1