LCOV - code coverage report
Current view: top level - src/backend/postmaster - launch_backend.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 84.4 % 32 27
Test Date: 2026-01-26 10:56:24 Functions: 50.0 % 2 1
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 75.0 % 16 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/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                 :             :         slock_t    *ShmemLock;
     100                 :             : #ifdef USE_INJECTION_POINTS
     101                 :             :         struct InjectionPointsCtl *ActiveInjectionPoints;
     102                 :             : #endif
     103                 :             :         int                     NamedLWLockTrancheRequests;
     104                 :             :         NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray;
     105                 :             :         char      **LWLockTrancheNames;
     106                 :             :         int                *LWLockCounter;
     107                 :             :         LWLockPadded *MainLWLockArray;
     108                 :             :         slock_t    *ProcStructLock;
     109                 :             :         PROC_HDR   *ProcGlobal;
     110                 :             :         PGPROC     *AuxiliaryProcs;
     111                 :             :         PGPROC     *PreparedXactProcs;
     112                 :             :         volatile PMSignalData *PMSignalState;
     113                 :             :         ProcSignalHeader *ProcSignal;
     114                 :             :         pid_t           PostmasterPid;
     115                 :             :         TimestampTz PgStartTime;
     116                 :             :         TimestampTz PgReloadTime;
     117                 :             :         pg_time_t       first_syslogger_file_time;
     118                 :             :         bool            redirection_done;
     119                 :             :         bool            IsBinaryUpgrade;
     120                 :             :         bool            query_id_enabled;
     121                 :             :         int                     max_safe_fds;
     122                 :             :         int                     MaxBackends;
     123                 :             :         int                     num_pmchild_slots;
     124                 :             : #ifdef WIN32
     125                 :             :         HANDLE          PostmasterHandle;
     126                 :             :         HANDLE          initial_signal_pipe;
     127                 :             :         HANDLE          syslogPipe[2];
     128                 :             : #else
     129                 :             :         int                     postmaster_alive_fds[2];
     130                 :             :         int                     syslogPipe[2];
     131                 :             : #endif
     132                 :             :         char            my_exec_path[MAXPGPATH];
     133                 :             :         char            pkglib_path[MAXPGPATH];
     134                 :             : 
     135                 :             :         int                     MyPMChildSlot;
     136                 :             : 
     137                 :             :         /*
     138                 :             :          * These are only used by backend processes, but are here because passing
     139                 :             :          * a socket needs some special handling on Windows. 'client_sock' is an
     140                 :             :          * explicit argument to postmaster_child_launch, but is stored in
     141                 :             :          * MyClientSocket in the child process.
     142                 :             :          */
     143                 :             :         ClientSocket client_sock;
     144                 :             :         InheritableSocket inh_sock;
     145                 :             : 
     146                 :             :         /*
     147                 :             :          * Extra startup data, content depends on the child process.
     148                 :             :          */
     149                 :             :         size_t          startup_data_len;
     150                 :             :         char            startup_data[FLEXIBLE_ARRAY_MEMBER];
     151                 :             : } BackendParameters;
     152                 :             : 
     153                 :             : #define SizeOfBackendParameters(startup_data_len) (offsetof(BackendParameters, startup_data) + startup_data_len)
     154                 :             : 
     155                 :             : static void read_backend_variables(char *id, void **startup_data, size_t *startup_data_len);
     156                 :             : static void restore_backend_variables(BackendParameters *param);
     157                 :             : 
     158                 :             : static bool save_backend_variables(BackendParameters *param, int child_slot,
     159                 :             :                                                                    ClientSocket *client_sock,
     160                 :             : #ifdef WIN32
     161                 :             :                                                                    HANDLE childProcess, pid_t childPid,
     162                 :             : #endif
     163                 :             :                                                                    const void *startup_data, size_t startup_data_len);
     164                 :             : 
     165                 :             : static pid_t internal_forkexec(BackendType child_kind, int child_slot,
     166                 :             :                                                            const void *startup_data, size_t startup_data_len,
     167                 :             :                                                            ClientSocket *client_sock);
     168                 :             : 
     169                 :             : #endif                                                  /* EXEC_BACKEND */
     170                 :             : 
     171                 :             : /*
     172                 :             :  * Information needed to launch different kinds of child processes.
     173                 :             :  */
     174                 :             : typedef struct
     175                 :             : {
     176                 :             :         const char *name;
     177                 :             :         void            (*main_fn) (const void *startup_data, size_t startup_data_len);
     178                 :             :         bool            shmem_attach;
     179                 :             : } child_process_kind;
     180                 :             : 
     181                 :             : static child_process_kind child_process_kinds[] = {
     182                 :             : #define PG_PROCTYPE(bktype, description, main_func, shmem_attach) \
     183                 :             :         [bktype] = {description, main_func, shmem_attach},
     184                 :             : #include "postmaster/proctypelist.h"
     185                 :             : #undef PG_PROCTYPE
     186                 :             : };
     187                 :             : 
     188                 :             : const char *
     189                 :           0 : PostmasterChildName(BackendType child_type)
     190                 :             : {
     191                 :           0 :         return child_process_kinds[child_type].name;
     192                 :             : }
     193                 :             : 
     194                 :             : /*
     195                 :             :  * Start a new postmaster child process.
     196                 :             :  *
     197                 :             :  * The child process will be restored to roughly the same state whether
     198                 :             :  * EXEC_BACKEND is used or not: it will be attached to shared memory if
     199                 :             :  * appropriate, and fds and other resources that we've inherited from
     200                 :             :  * postmaster that are not needed in a child process have been closed.
     201                 :             :  *
     202                 :             :  * 'child_slot' is the PMChildFlags array index reserved for the child
     203                 :             :  * process.  'startup_data' is an optional contiguous chunk of data that is
     204                 :             :  * passed to the child process.
     205                 :             :  */
     206                 :             : pid_t
     207                 :         812 : postmaster_child_launch(BackendType child_type, int child_slot,
     208                 :             :                                                 void *startup_data, size_t startup_data_len,
     209                 :             :                                                 ClientSocket *client_sock)
     210                 :             : {
     211                 :         812 :         pid_t           pid;
     212                 :             : 
     213         [ +  - ]:         812 :         Assert(IsPostmasterEnvironment && !IsUnderPostmaster);
     214                 :             : 
     215                 :             :         /* Capture time Postmaster initiates process creation for logging */
     216   [ +  +  -  + ]:         812 :         if (IsExternalConnectionBackend(child_type))
     217                 :         316 :                 ((BackendStartupData *) startup_data)->fork_started = GetCurrentTimestamp();
     218                 :             : 
     219                 :             : #ifdef EXEC_BACKEND
     220                 :             :         pid = internal_forkexec(child_type, child_slot,
     221                 :             :                                                         startup_data, startup_data_len, client_sock);
     222                 :             :         /* the child process will arrive in SubPostmasterMain */
     223                 :             : #else                                                   /* !EXEC_BACKEND */
     224                 :         812 :         pid = fork_process();
     225         [ +  + ]:         812 :         if (pid == 0)                           /* child */
     226                 :             :         {
     227                 :             :                 /* Capture and transfer timings that may be needed for logging */
     228   [ +  +  -  + ]:         804 :                 if (IsExternalConnectionBackend(child_type))
     229                 :             :                 {
     230                 :         315 :                         conn_timing.socket_create =
     231                 :         315 :                                 ((BackendStartupData *) startup_data)->socket_created;
     232                 :         315 :                         conn_timing.fork_start =
     233                 :         315 :                                 ((BackendStartupData *) startup_data)->fork_started;
     234                 :         315 :                         conn_timing.fork_end = GetCurrentTimestamp();
     235                 :         315 :                 }
     236                 :             : 
     237                 :             :                 /* Close the postmaster's sockets */
     238                 :         804 :                 ClosePostmasterPorts(child_type == B_LOGGER);
     239                 :             : 
     240                 :             :                 /* Detangle from postmaster */
     241                 :         804 :                 InitPostmasterChild();
     242                 :             : 
     243                 :             :                 /* Detach shared memory if not needed. */
     244         [ +  - ]:         804 :                 if (!child_process_kinds[child_type].shmem_attach)
     245                 :             :                 {
     246                 :           0 :                         dsm_detach_all();
     247                 :           0 :                         PGSharedMemoryDetach();
     248                 :           0 :                 }
     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                 :         804 :                 MemoryContextSwitchTo(TopMemoryContext);
     257                 :             : 
     258                 :         804 :                 MyPMChildSlot = child_slot;
     259         [ +  + ]:         804 :                 if (client_sock)
     260                 :             :                 {
     261                 :         315 :                         MyClientSocket = palloc_object(ClientSocket);
     262                 :         315 :                         memcpy(MyClientSocket, client_sock, sizeof(ClientSocket));
     263                 :         315 :                 }
     264                 :             : 
     265                 :             :                 /*
     266                 :             :                  * Run the appropriate Main function
     267                 :             :                  */
     268                 :         804 :                 child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
     269                 :         804 :                 pg_unreachable();               /* main_fn never returns */
     270                 :             :         }
     271                 :             : #endif                                                  /* EXEC_BACKEND */
     272                 :          16 :         return pid;
     273                 :           8 : }
     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, 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, 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                 :             : 
     612                 :             :         /* Read in the variables file */
     613                 :             :         read_backend_variables(argv[2], &startup_data, &startup_data_len);
     614                 :             : 
     615                 :             :         /* Close the postmaster's sockets (as soon as we know them) */
     616                 :             :         ClosePostmasterPorts(child_type == B_LOGGER);
     617                 :             : 
     618                 :             :         /* Setup as postmaster child */
     619                 :             :         InitPostmasterChild();
     620                 :             : 
     621                 :             :         /*
     622                 :             :          * If appropriate, physically re-attach to shared memory segment. We want
     623                 :             :          * to do this before going any further to ensure that we can attach at the
     624                 :             :          * same address the postmaster used.  On the other hand, if we choose not
     625                 :             :          * to re-attach, we may have other cleanup to do.
     626                 :             :          *
     627                 :             :          * If testing EXEC_BACKEND on Linux, you should run this as root before
     628                 :             :          * starting the postmaster:
     629                 :             :          *
     630                 :             :          * sysctl -w kernel.randomize_va_space=0
     631                 :             :          *
     632                 :             :          * This prevents using randomized stack and code addresses that cause the
     633                 :             :          * child process's memory map to be different from the parent's, making it
     634                 :             :          * sometimes impossible to attach to shared memory at the desired address.
     635                 :             :          * Return the setting to its old value (usually '1' or '2') when finished.
     636                 :             :          */
     637                 :             :         if (child_process_kinds[child_type].shmem_attach)
     638                 :             :                 PGSharedMemoryReAttach();
     639                 :             :         else
     640                 :             :                 PGSharedMemoryNoReAttach();
     641                 :             : 
     642                 :             :         /* Read in remaining GUC variables */
     643                 :             :         read_nondefault_variables();
     644                 :             : 
     645                 :             :         /* Capture and transfer timings that may be needed for log_connections */
     646                 :             :         if (IsExternalConnectionBackend(child_type))
     647                 :             :         {
     648                 :             :                 conn_timing.socket_create =
     649                 :             :                         ((BackendStartupData *) startup_data)->socket_created;
     650                 :             :                 conn_timing.fork_start =
     651                 :             :                         ((BackendStartupData *) startup_data)->fork_started;
     652                 :             :                 conn_timing.fork_end = fork_end;
     653                 :             :         }
     654                 :             : 
     655                 :             :         /*
     656                 :             :          * Check that the data directory looks valid, which will also check the
     657                 :             :          * privileges on the data directory and update our umask and file/group
     658                 :             :          * variables for creating files later.  Note: this should really be done
     659                 :             :          * before we create any files or directories.
     660                 :             :          */
     661                 :             :         checkDataDir();
     662                 :             : 
     663                 :             :         /*
     664                 :             :          * (re-)read control file, as it contains config. The postmaster will
     665                 :             :          * already have read this, but this process doesn't know about that.
     666                 :             :          */
     667                 :             :         LocalProcessControlFile(false);
     668                 :             : 
     669                 :             :         /*
     670                 :             :          * Reload any libraries that were preloaded by the postmaster.  Since we
     671                 :             :          * exec'd this process, those libraries didn't come along with us; but we
     672                 :             :          * should load them into all child processes to be consistent with the
     673                 :             :          * non-EXEC_BACKEND behavior.
     674                 :             :          */
     675                 :             :         process_shared_preload_libraries();
     676                 :             : 
     677                 :             :         /* Restore basic shared memory pointers */
     678                 :             :         if (UsedShmemSegAddr != NULL)
     679                 :             :                 InitShmemAccess(UsedShmemSegAddr);
     680                 :             : 
     681                 :             :         /*
     682                 :             :          * Run the appropriate Main function
     683                 :             :          */
     684                 :             :         child_process_kinds[child_type].main_fn(startup_data, startup_data_len);
     685                 :             :         pg_unreachable();                       /* main_fn never returns */
     686                 :             : }
     687                 :             : 
     688                 :             : #ifndef WIN32
     689                 :             : #define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
     690                 :             : #define read_inheritable_socket(dest, src) (*(dest) = *(src))
     691                 :             : #else
     692                 :             : static bool write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
     693                 :             : static bool write_inheritable_socket(InheritableSocket *dest, SOCKET src,
     694                 :             :                                                                          pid_t childPid);
     695                 :             : static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
     696                 :             : #endif
     697                 :             : 
     698                 :             : 
     699                 :             : /* Save critical backend variables into the BackendParameters struct */
     700                 :             : static bool
     701                 :             : save_backend_variables(BackendParameters *param,
     702                 :             :                                            int child_slot, ClientSocket *client_sock,
     703                 :             : #ifdef WIN32
     704                 :             :                                            HANDLE childProcess, pid_t childPid,
     705                 :             : #endif
     706                 :             :                                            const void *startup_data, size_t startup_data_len)
     707                 :             : {
     708                 :             :         if (client_sock)
     709                 :             :                 memcpy(&param->client_sock, client_sock, sizeof(ClientSocket));
     710                 :             :         else
     711                 :             :                 memset(&param->client_sock, 0, sizeof(ClientSocket));
     712                 :             :         if (!write_inheritable_socket(&param->inh_sock,
     713                 :             :                                                                   client_sock ? client_sock->sock : PGINVALID_SOCKET,
     714                 :             :                                                                   childPid))
     715                 :             :                 return false;
     716                 :             : 
     717                 :             :         strlcpy(param->DataDir, DataDir, MAXPGPATH);
     718                 :             : 
     719                 :             :         param->MyPMChildSlot = child_slot;
     720                 :             : 
     721                 :             : #ifdef WIN32
     722                 :             :         param->ShmemProtectiveRegion = ShmemProtectiveRegion;
     723                 :             : #endif
     724                 :             :         param->UsedShmemSegID = UsedShmemSegID;
     725                 :             :         param->UsedShmemSegAddr = UsedShmemSegAddr;
     726                 :             : 
     727                 :             :         param->ShmemLock = ShmemLock;
     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                 :             :         ShmemLock = param->ShmemLock;
     990                 :             : 
     991                 :             : #ifdef USE_INJECTION_POINTS
     992                 :             :         ActiveInjectionPoints = param->ActiveInjectionPoints;
     993                 :             : #endif
     994                 :             : 
     995                 :             :         NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests;
     996                 :             :         NamedLWLockTrancheRequestArray = param->NamedLWLockTrancheRequestArray;
     997                 :             :         LWLockTrancheNames = param->LWLockTrancheNames;
     998                 :             :         LWLockCounter = param->LWLockCounter;
     999                 :             :         MainLWLockArray = param->MainLWLockArray;
    1000                 :             :         ProcStructLock = param->ProcStructLock;
    1001                 :             :         ProcGlobal = param->ProcGlobal;
    1002                 :             :         AuxiliaryProcs = param->AuxiliaryProcs;
    1003                 :             :         PreparedXactProcs = param->PreparedXactProcs;
    1004                 :             :         PMSignalState = param->PMSignalState;
    1005                 :             :         ProcSignal = param->ProcSignal;
    1006                 :             : 
    1007                 :             :         PostmasterPid = param->PostmasterPid;
    1008                 :             :         PgStartTime = param->PgStartTime;
    1009                 :             :         PgReloadTime = param->PgReloadTime;
    1010                 :             :         first_syslogger_file_time = param->first_syslogger_file_time;
    1011                 :             : 
    1012                 :             :         redirection_done = param->redirection_done;
    1013                 :             :         IsBinaryUpgrade = param->IsBinaryUpgrade;
    1014                 :             :         query_id_enabled = param->query_id_enabled;
    1015                 :             :         max_safe_fds = param->max_safe_fds;
    1016                 :             : 
    1017                 :             :         MaxBackends = param->MaxBackends;
    1018                 :             :         num_pmchild_slots = param->num_pmchild_slots;
    1019                 :             : 
    1020                 :             : #ifdef WIN32
    1021                 :             :         PostmasterHandle = param->PostmasterHandle;
    1022                 :             :         pgwin32_initial_signal_pipe = param->initial_signal_pipe;
    1023                 :             : #else
    1024                 :             :         memcpy(&postmaster_alive_fds, &param->postmaster_alive_fds,
    1025                 :             :                    sizeof(postmaster_alive_fds));
    1026                 :             : #endif
    1027                 :             : 
    1028                 :             :         memcpy(&syslogPipe, &param->syslogPipe, sizeof(syslogPipe));
    1029                 :             : 
    1030                 :             :         strlcpy(my_exec_path, param->my_exec_path, MAXPGPATH);
    1031                 :             : 
    1032                 :             :         strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
    1033                 :             : 
    1034                 :             :         /*
    1035                 :             :          * We need to restore fd.c's counts of externally-opened FDs; to avoid
    1036                 :             :          * confusion, be sure to do this after restoring max_safe_fds.  (Note:
    1037                 :             :          * BackendInitialize will handle this for (*client_sock)->sock.)
    1038                 :             :          */
    1039                 :             : #ifndef WIN32
    1040                 :             :         if (postmaster_alive_fds[0] >= 0)
    1041                 :             :                 ReserveExternalFD();
    1042                 :             :         if (postmaster_alive_fds[1] >= 0)
    1043                 :             :                 ReserveExternalFD();
    1044                 :             : #endif
    1045                 :             : }
    1046                 :             : 
    1047                 :             : #endif                                                  /* EXEC_BACKEND */
        

Generated by: LCOV version 2.3.2-1