LCOV - code coverage report
Current view: top level - src/bin/pg_dump - parallel.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 82.2 % 325 267
Test Date: 2026-07-11 05:15:30 Functions: 90.6 % 32 29
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 63.2 % 163 103

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * parallel.c
       4                 :             :  *
       5                 :             :  *  Parallel support for pg_dump and pg_restore
       6                 :             :  *
       7                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       8                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *      src/bin/pg_dump/parallel.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : 
      16                 :             : /*
      17                 :             :  * Parallel operation works like this:
      18                 :             :  *
      19                 :             :  * The original, leader process calls ParallelBackupStart(), which forks off
      20                 :             :  * the desired number of worker processes, which each enter WaitForCommands().
      21                 :             :  *
      22                 :             :  * The leader process dispatches an individual work item to one of the worker
      23                 :             :  * processes in DispatchJobForTocEntry().  We send a command string such as
      24                 :             :  * "DUMP 1234" or "RESTORE 1234", where 1234 is the TocEntry ID.
      25                 :             :  * The worker process receives and decodes the command and passes it to the
      26                 :             :  * routine pointed to by AH->WorkerJobDumpPtr or AH->WorkerJobRestorePtr,
      27                 :             :  * which are routines of the current archive format.  That routine performs
      28                 :             :  * the required action (dump or restore) and returns an integer status code.
      29                 :             :  * This is passed back to the leader where we pass it to the
      30                 :             :  * ParallelCompletionPtr callback function that was passed to
      31                 :             :  * DispatchJobForTocEntry().  The callback function does state updating
      32                 :             :  * for the leader control logic in pg_backup_archiver.c.
      33                 :             :  *
      34                 :             :  * In principle additional archive-format-specific information might be needed
      35                 :             :  * in commands or worker status responses, but so far that hasn't proved
      36                 :             :  * necessary, since workers have full copies of the ArchiveHandle/TocEntry
      37                 :             :  * data structures.  Remember that we have forked off the workers only after
      38                 :             :  * we have read in the catalog.  That's why our worker processes can also
      39                 :             :  * access the catalog information.  (In the Windows case, the workers are
      40                 :             :  * threads in the same process.  To avoid problems, they work with cloned
      41                 :             :  * copies of the Archive data structure; see RunWorker().)
      42                 :             :  *
      43                 :             :  * In the leader process, the workerStatus field for each worker has one of
      44                 :             :  * the following values:
      45                 :             :  *      WRKR_NOT_STARTED: we've not yet forked this worker
      46                 :             :  *      WRKR_IDLE: it's waiting for a command
      47                 :             :  *      WRKR_WORKING: it's working on a command
      48                 :             :  *      WRKR_TERMINATED: process ended
      49                 :             :  * The pstate->te[] entry for each worker is valid when it's in WRKR_WORKING
      50                 :             :  * state, and must be NULL in other states.
      51                 :             :  */
      52                 :             : 
      53                 :             : #include "postgres_fe.h"
      54                 :             : 
      55                 :             : #ifndef WIN32
      56                 :             : #include <sys/select.h>
      57                 :             : #include <sys/wait.h>
      58                 :             : #include <signal.h>
      59                 :             : #include <unistd.h>
      60                 :             : #include <fcntl.h>
      61                 :             : #endif
      62                 :             : 
      63                 :             : #include "fe_utils/string_utils.h"
      64                 :             : #include "parallel.h"
      65                 :             : #include "pg_backup_utils.h"
      66                 :             : #ifdef WIN32
      67                 :             : #include "port/pg_bswap.h"
      68                 :             : #endif
      69                 :             : 
      70                 :             : /* Mnemonic macros for indexing the fd array returned by pipe(2) */
      71                 :             : #define PIPE_READ                           0
      72                 :             : #define PIPE_WRITE                          1
      73                 :             : 
      74                 :             : #define NO_SLOT (-1)            /* Failure result for GetIdleWorker() */
      75                 :             : 
      76                 :             : /* Worker process statuses */
      77                 :             : typedef enum
      78                 :             : {
      79                 :             :     WRKR_NOT_STARTED = 0,
      80                 :             :     WRKR_IDLE,
      81                 :             :     WRKR_WORKING,
      82                 :             :     WRKR_TERMINATED,
      83                 :             : } T_WorkerStatus;
      84                 :             : 
      85                 :             : #define WORKER_IS_RUNNING(workerStatus) \
      86                 :             :     ((workerStatus) == WRKR_IDLE || (workerStatus) == WRKR_WORKING)
      87                 :             : 
      88                 :             : /*
      89                 :             :  * Private per-parallel-worker state (typedef for this is in parallel.h).
      90                 :             :  *
      91                 :             :  * Much of this is valid only in the leader process (or, on Windows, should
      92                 :             :  * be touched only by the leader thread).  But the AH field should be touched
      93                 :             :  * only by workers.  The pipe descriptors are valid everywhere.
      94                 :             :  */
      95                 :             : struct ParallelSlot
      96                 :             : {
      97                 :             :     T_WorkerStatus workerStatus;    /* see enum above */
      98                 :             : 
      99                 :             :     /* These fields are valid if workerStatus == WRKR_WORKING: */
     100                 :             :     ParallelCompletionPtr callback; /* function to call on completion */
     101                 :             :     void       *callback_data;  /* passthrough data for it */
     102                 :             : 
     103                 :             :     ArchiveHandle *AH;          /* Archive data worker is using */
     104                 :             : 
     105                 :             :     int         pipeRead;       /* leader's end of the pipes */
     106                 :             :     int         pipeWrite;
     107                 :             :     int         pipeRevRead;    /* child's end of the pipes */
     108                 :             :     int         pipeRevWrite;
     109                 :             : 
     110                 :             :     /* Child process/thread identity info: */
     111                 :             : #ifdef WIN32
     112                 :             :     uintptr_t   hThread;
     113                 :             :     unsigned int threadId;
     114                 :             : #else
     115                 :             :     pid_t       pid;
     116                 :             : #endif
     117                 :             : };
     118                 :             : 
     119                 :             : #ifdef WIN32
     120                 :             : 
     121                 :             : /*
     122                 :             :  * Structure to hold info passed by _beginthreadex() to the function it calls
     123                 :             :  * via its single allowed argument.
     124                 :             :  */
     125                 :             : typedef struct
     126                 :             : {
     127                 :             :     ArchiveHandle *AH;          /* leader database connection */
     128                 :             :     ParallelSlot *slot;         /* this worker's parallel slot */
     129                 :             : } WorkerInfo;
     130                 :             : 
     131                 :             : /* Windows implementation of pipe access */
     132                 :             : static int  pgpipe(int handles[2]);
     133                 :             : #define piperead(a,b,c)     recv(a,b,c,0)
     134                 :             : #define pipewrite(a,b,c)    send(a,b,c,0)
     135                 :             : 
     136                 :             : #else                           /* !WIN32 */
     137                 :             : 
     138                 :             : /* Non-Windows implementation of pipe access */
     139                 :             : #define pgpipe(a)           pipe(a)
     140                 :             : #define piperead(a,b,c)     read(a,b,c)
     141                 :             : #define pipewrite(a,b,c)    write(a,b,c)
     142                 :             : 
     143                 :             : #endif                          /* WIN32 */
     144                 :             : 
     145                 :             : /*
     146                 :             :  * State info for archive_close_connection() shutdown callback.
     147                 :             :  */
     148                 :             : typedef struct ShutdownInformation
     149                 :             : {
     150                 :             :     ParallelState *pstate;
     151                 :             :     Archive    *AHX;
     152                 :             : } ShutdownInformation;
     153                 :             : 
     154                 :             : static ShutdownInformation shutdown_info;
     155                 :             : 
     156                 :             : /*
     157                 :             :  * State info for signal handling.
     158                 :             :  * We assume signal_info initializes to zeroes.
     159                 :             :  *
     160                 :             :  * On Unix, myAH is the leader DB connection in the leader process, and the
     161                 :             :  * worker's own connection in worker processes.  On Windows, we have only one
     162                 :             :  * instance of signal_info, so myAH is the leader connection and the worker
     163                 :             :  * connections must be dug out of pstate->parallelSlot[].
     164                 :             :  */
     165                 :             : typedef struct DumpSignalInformation
     166                 :             : {
     167                 :             :     ArchiveHandle *myAH;        /* database connection to issue cancel for */
     168                 :             :     ParallelState *pstate;      /* parallel state, if any */
     169                 :             :     bool        handler_set;    /* signal handler set up in this process? */
     170                 :             : #ifndef WIN32
     171                 :             :     bool        am_worker;      /* am I a worker process? */
     172                 :             : #endif
     173                 :             : } DumpSignalInformation;
     174                 :             : 
     175                 :             : static volatile DumpSignalInformation signal_info;
     176                 :             : 
     177                 :             : #ifdef WIN32
     178                 :             : static CRITICAL_SECTION signal_info_lock;
     179                 :             : #endif
     180                 :             : 
     181                 :             : /*
     182                 :             :  * Write a simple string to stderr --- must be safe in a signal handler.
     183                 :             :  * We ignore the write() result since there's not much we could do about it.
     184                 :             :  * Certain compilers make that harder than it ought to be.
     185                 :             :  */
     186                 :             : #define write_stderr(str) \
     187                 :             :     do { \
     188                 :             :         const char *str_ = (str); \
     189                 :             :         int     rc_; \
     190                 :             :         rc_ = write(fileno(stderr), str_, strlen(str_)); \
     191                 :             :         (void) rc_; \
     192                 :             :     } while (0)
     193                 :             : 
     194                 :             : 
     195                 :             : #ifdef WIN32
     196                 :             : /* file-scope variables */
     197                 :             : static DWORD tls_index;
     198                 :             : 
     199                 :             : /* globally visible variables (needed by exit_nicely) */
     200                 :             : bool        parallel_init_done = false;
     201                 :             : DWORD       mainThreadId;
     202                 :             : #endif                          /* WIN32 */
     203                 :             : 
     204                 :             : /* Local function prototypes */
     205                 :             : static ParallelSlot *GetMyPSlot(ParallelState *pstate);
     206                 :             : static void archive_close_connection(int code, void *arg);
     207                 :             : static void ShutdownWorkersHard(ParallelState *pstate);
     208                 :             : static void WaitForTerminatingWorkers(ParallelState *pstate);
     209                 :             : static void set_cancel_handler(void);
     210                 :             : static void set_cancel_pstate(ParallelState *pstate);
     211                 :             : static void set_cancel_slot_archive(ParallelSlot *slot, ArchiveHandle *AH);
     212                 :             : static void RunWorker(ArchiveHandle *AH, ParallelSlot *slot);
     213                 :             : static int  GetIdleWorker(ParallelState *pstate);
     214                 :             : static bool HasEveryWorkerTerminated(ParallelState *pstate);
     215                 :             : static void lockTableForWorker(ArchiveHandle *AH, TocEntry *te);
     216                 :             : static void WaitForCommands(ArchiveHandle *AH, int pipefd[2]);
     217                 :             : static bool ListenToWorkers(ArchiveHandle *AH, ParallelState *pstate,
     218                 :             :                             bool do_wait);
     219                 :             : static char *getMessageFromLeader(int pipefd[2]);
     220                 :             : static void sendMessageToLeader(int pipefd[2], const char *str);
     221                 :             : static int  select_loop(int maxFd, fd_set *workerset);
     222                 :             : static char *getMessageFromWorker(ParallelState *pstate,
     223                 :             :                                   bool do_wait, int *worker);
     224                 :             : static void sendMessageToWorker(ParallelState *pstate,
     225                 :             :                                 int worker, const char *str);
     226                 :             : static char *readMessageFromPipe(int fd);
     227                 :             : 
     228                 :             : #define messageStartsWith(msg, prefix) \
     229                 :             :     (strncmp(msg, prefix, strlen(prefix)) == 0)
     230                 :             : 
     231                 :             : 
     232                 :             : /*
     233                 :             :  * Initialize parallel dump support --- should be called early in process
     234                 :             :  * startup.  (Currently, this is called whether or not we intend parallel
     235                 :             :  * activity.)
     236                 :             :  */
     237                 :             : void
     238                 :         403 : init_parallel_dump_utils(void)
     239                 :             : {
     240                 :             : #ifdef WIN32
     241                 :             :     if (!parallel_init_done)
     242                 :             :     {
     243                 :             :         WSADATA     wsaData;
     244                 :             :         int         err;
     245                 :             : 
     246                 :             :         /* Prepare for threaded operation */
     247                 :             :         tls_index = TlsAlloc();
     248                 :             :         mainThreadId = GetCurrentThreadId();
     249                 :             : 
     250                 :             :         /* Initialize socket access */
     251                 :             :         err = WSAStartup(MAKEWORD(2, 2), &wsaData);
     252                 :             :         if (err != 0)
     253                 :             :             pg_fatal("%s() failed: error code %d", "WSAStartup", err);
     254                 :             : 
     255                 :             :         parallel_init_done = true;
     256                 :             :     }
     257                 :             : #endif
     258                 :         403 : }
     259                 :             : 
     260                 :             : /*
     261                 :             :  * Find the ParallelSlot for the current worker process or thread.
     262                 :             :  *
     263                 :             :  * Returns NULL if no matching slot is found (this implies we're the leader).
     264                 :             :  */
     265                 :             : static ParallelSlot *
     266                 :           0 : GetMyPSlot(ParallelState *pstate)
     267                 :             : {
     268                 :             :     int         i;
     269                 :             : 
     270         [ #  # ]:           0 :     for (i = 0; i < pstate->numWorkers; i++)
     271                 :             :     {
     272                 :             : #ifdef WIN32
     273                 :             :         if (pstate->parallelSlot[i].threadId == GetCurrentThreadId())
     274                 :             : #else
     275         [ #  # ]:           0 :         if (pstate->parallelSlot[i].pid == getpid())
     276                 :             : #endif
     277                 :           0 :             return &(pstate->parallelSlot[i]);
     278                 :             :     }
     279                 :             : 
     280                 :           0 :     return NULL;
     281                 :             : }
     282                 :             : 
     283                 :             : /*
     284                 :             :  * A thread-local version of getLocalPQExpBuffer().
     285                 :             :  *
     286                 :             :  * Non-reentrant but reduces memory leakage: we'll consume one buffer per
     287                 :             :  * thread, which is much better than one per fmtId/fmtQualifiedId call.
     288                 :             :  */
     289                 :             : #ifdef WIN32
     290                 :             : static PQExpBuffer
     291                 :             : getThreadLocalPQExpBuffer(void)
     292                 :             : {
     293                 :             :     /*
     294                 :             :      * The Tls code goes awry if we use a static var, so we provide for both
     295                 :             :      * static and auto, and omit any use of the static var when using Tls. We
     296                 :             :      * rely on TlsGetValue() to return 0 if the value is not yet set.
     297                 :             :      */
     298                 :             :     static PQExpBuffer s_id_return = NULL;
     299                 :             :     PQExpBuffer id_return;
     300                 :             : 
     301                 :             :     if (parallel_init_done)
     302                 :             :         id_return = (PQExpBuffer) TlsGetValue(tls_index);
     303                 :             :     else
     304                 :             :         id_return = s_id_return;
     305                 :             : 
     306                 :             :     if (id_return)              /* first time through? */
     307                 :             :     {
     308                 :             :         /* same buffer, just wipe contents */
     309                 :             :         resetPQExpBuffer(id_return);
     310                 :             :     }
     311                 :             :     else
     312                 :             :     {
     313                 :             :         /* new buffer */
     314                 :             :         id_return = createPQExpBuffer();
     315                 :             :         if (parallel_init_done)
     316                 :             :             TlsSetValue(tls_index, id_return);
     317                 :             :         else
     318                 :             :             s_id_return = id_return;
     319                 :             :     }
     320                 :             : 
     321                 :             :     return id_return;
     322                 :             : }
     323                 :             : #endif                          /* WIN32 */
     324                 :             : 
     325                 :             : /*
     326                 :             :  * pg_dump and pg_restore call this to register the cleanup handler
     327                 :             :  * as soon as they've created the ArchiveHandle.
     328                 :             :  */
     329                 :             : void
     330                 :         275 : on_exit_close_archive(Archive *AHX)
     331                 :             : {
     332                 :         275 :     shutdown_info.AHX = AHX;
     333                 :         275 :     on_exit_nicely(archive_close_connection, &shutdown_info);
     334                 :         275 : }
     335                 :             : 
     336                 :             : /*
     337                 :             :  * on_exit_nicely handler for shutting down database connections and
     338                 :             :  * worker processes cleanly.
     339                 :             :  */
     340                 :             : static void
     341                 :         210 : archive_close_connection(int code, void *arg)
     342                 :             : {
     343                 :         210 :     ShutdownInformation *si = (ShutdownInformation *) arg;
     344                 :             : 
     345         [ -  + ]:         210 :     if (si->pstate)
     346                 :             :     {
     347                 :             :         /* In parallel mode, must figure out who we are */
     348                 :           0 :         ParallelSlot *slot = GetMyPSlot(si->pstate);
     349                 :             : 
     350         [ #  # ]:           0 :         if (!slot)
     351                 :             :         {
     352                 :             :             /*
     353                 :             :              * We're the leader.  Forcibly shut down workers, then close our
     354                 :             :              * own database connection, if any.
     355                 :             :              */
     356                 :           0 :             ShutdownWorkersHard(si->pstate);
     357                 :             : 
     358         [ #  # ]:           0 :             if (si->AHX)
     359                 :           0 :                 DisconnectDatabase(si->AHX);
     360                 :             :         }
     361                 :             :         else
     362                 :             :         {
     363                 :             :             /*
     364                 :             :              * We're a worker.  Shut down our own DB connection if any.  On
     365                 :             :              * Windows, we also have to close our communication sockets, to
     366                 :             :              * emulate what will happen on Unix when the worker process exits.
     367                 :             :              * (Without this, if this is a premature exit, the leader would
     368                 :             :              * fail to detect it because there would be no EOF condition on
     369                 :             :              * the other end of the pipe.)
     370                 :             :              */
     371         [ #  # ]:           0 :             if (slot->AH)
     372                 :           0 :                 DisconnectDatabase(&(slot->AH->public));
     373                 :             : 
     374                 :             : #ifdef WIN32
     375                 :             :             closesocket(slot->pipeRevRead);
     376                 :             :             closesocket(slot->pipeRevWrite);
     377                 :             : #endif
     378                 :             :         }
     379                 :             :     }
     380                 :             :     else
     381                 :             :     {
     382                 :             :         /* Non-parallel operation: just kill the leader DB connection */
     383         [ +  - ]:         210 :         if (si->AHX)
     384                 :         210 :             DisconnectDatabase(si->AHX);
     385                 :             :     }
     386                 :         210 : }
     387                 :             : 
     388                 :             : /*
     389                 :             :  * Forcibly shut down any remaining workers, waiting for them to finish.
     390                 :             :  *
     391                 :             :  * Note that we don't expect to come here during normal exit (the workers
     392                 :             :  * should be long gone, and the ParallelState too).  We're only here in a
     393                 :             :  * pg_fatal() situation, so intervening to cancel active commands is
     394                 :             :  * appropriate.
     395                 :             :  */
     396                 :             : static void
     397                 :           0 : ShutdownWorkersHard(ParallelState *pstate)
     398                 :             : {
     399                 :             :     int         i;
     400                 :             : 
     401                 :             :     /*
     402                 :             :      * Close our write end of the sockets so that any workers waiting for
     403                 :             :      * commands know they can exit.  (Note: some of the pipeWrite fields might
     404                 :             :      * still be zero, if we failed to initialize all the workers.  Hence, just
     405                 :             :      * ignore errors here.)
     406                 :             :      */
     407         [ #  # ]:           0 :     for (i = 0; i < pstate->numWorkers; i++)
     408                 :           0 :         closesocket(pstate->parallelSlot[i].pipeWrite);
     409                 :             : 
     410                 :             :     /*
     411                 :             :      * Force early termination of any commands currently in progress.
     412                 :             :      */
     413                 :             : #ifndef WIN32
     414                 :             :     /* On non-Windows, send SIGTERM to each worker process. */
     415         [ #  # ]:           0 :     for (i = 0; i < pstate->numWorkers; i++)
     416                 :             :     {
     417                 :           0 :         pid_t       pid = pstate->parallelSlot[i].pid;
     418                 :             : 
     419         [ #  # ]:           0 :         if (pid != 0)
     420                 :           0 :             kill(pid, SIGTERM);
     421                 :             :     }
     422                 :             : #else
     423                 :             : 
     424                 :             :     /*
     425                 :             :      * On Windows, send query cancels directly to the workers' backends.  Use
     426                 :             :      * a critical section to ensure worker threads don't change state.
     427                 :             :      */
     428                 :             :     EnterCriticalSection(&signal_info_lock);
     429                 :             :     for (i = 0; i < pstate->numWorkers; i++)
     430                 :             :     {
     431                 :             :         ArchiveHandle *AH = pstate->parallelSlot[i].AH;
     432                 :             :         char        errbuf[1];
     433                 :             : 
     434                 :             :         if (AH != NULL && AH->connCancel != NULL)
     435                 :             :             (void) PQcancel(AH->connCancel, errbuf, sizeof(errbuf));
     436                 :             :     }
     437                 :             :     LeaveCriticalSection(&signal_info_lock);
     438                 :             : #endif
     439                 :             : 
     440                 :             :     /* Now wait for them to terminate. */
     441                 :           0 :     WaitForTerminatingWorkers(pstate);
     442                 :           0 : }
     443                 :             : 
     444                 :             : /*
     445                 :             :  * Wait for all workers to terminate.
     446                 :             :  */
     447                 :             : static void
     448                 :          12 : WaitForTerminatingWorkers(ParallelState *pstate)
     449                 :             : {
     450         [ +  + ]:          38 :     while (!HasEveryWorkerTerminated(pstate))
     451                 :             :     {
     452                 :          26 :         ParallelSlot *slot = NULL;
     453                 :             :         int         j;
     454                 :             : 
     455                 :             : #ifndef WIN32
     456                 :             :         /* On non-Windows, use wait() to wait for next worker to end */
     457                 :             :         int         status;
     458                 :          26 :         pid_t       pid = wait(&status);
     459                 :             : 
     460                 :             :         /* Find dead worker's slot, and clear the PID field */
     461         [ +  - ]:          42 :         for (j = 0; j < pstate->numWorkers; j++)
     462                 :             :         {
     463                 :          42 :             slot = &(pstate->parallelSlot[j]);
     464         [ +  + ]:          42 :             if (slot->pid == pid)
     465                 :             :             {
     466                 :          26 :                 slot->pid = 0;
     467                 :          26 :                 break;
     468                 :             :             }
     469                 :             :         }
     470                 :             : #else                           /* WIN32 */
     471                 :             :         /* On Windows, we must use WaitForMultipleObjects() */
     472                 :             :         HANDLE     *lpHandles = pg_malloc_array(HANDLE, pstate->numWorkers);
     473                 :             :         int         nrun = 0;
     474                 :             :         DWORD       ret;
     475                 :             :         uintptr_t   hThread;
     476                 :             : 
     477                 :             :         for (j = 0; j < pstate->numWorkers; j++)
     478                 :             :         {
     479                 :             :             if (WORKER_IS_RUNNING(pstate->parallelSlot[j].workerStatus))
     480                 :             :             {
     481                 :             :                 lpHandles[nrun] = (HANDLE) pstate->parallelSlot[j].hThread;
     482                 :             :                 nrun++;
     483                 :             :             }
     484                 :             :         }
     485                 :             :         ret = WaitForMultipleObjects(nrun, lpHandles, false, INFINITE);
     486                 :             :         Assert(ret != WAIT_FAILED);
     487                 :             :         hThread = (uintptr_t) lpHandles[ret - WAIT_OBJECT_0];
     488                 :             :         pg_free(lpHandles);
     489                 :             : 
     490                 :             :         /* Find dead worker's slot, and clear the hThread field */
     491                 :             :         for (j = 0; j < pstate->numWorkers; j++)
     492                 :             :         {
     493                 :             :             slot = &(pstate->parallelSlot[j]);
     494                 :             :             if (slot->hThread == hThread)
     495                 :             :             {
     496                 :             :                 /* For cleanliness, close handles for dead threads */
     497                 :             :                 CloseHandle((HANDLE) slot->hThread);
     498                 :             :                 slot->hThread = (uintptr_t) INVALID_HANDLE_VALUE;
     499                 :             :                 break;
     500                 :             :             }
     501                 :             :         }
     502                 :             : #endif                          /* WIN32 */
     503                 :             : 
     504                 :             :         /* On all platforms, update workerStatus and te[] as well */
     505                 :             :         Assert(j < pstate->numWorkers);
     506                 :          26 :         slot->workerStatus = WRKR_TERMINATED;
     507                 :          26 :         pstate->te[j] = NULL;
     508                 :             :     }
     509                 :          12 : }
     510                 :             : 
     511                 :             : 
     512                 :             : /*
     513                 :             :  * Code for responding to cancel interrupts (SIGINT, control-C, etc)
     514                 :             :  *
     515                 :             :  * This doesn't quite belong in this module, but it needs access to the
     516                 :             :  * ParallelState data, so there's not really a better place either.
     517                 :             :  *
     518                 :             :  * When we get a cancel interrupt, we could just die, but in pg_restore that
     519                 :             :  * could leave a SQL command (e.g., CREATE INDEX on a large table) running
     520                 :             :  * for a long time.  Instead, we try to send a cancel request and then die.
     521                 :             :  * pg_dump probably doesn't really need this, but we might as well use it
     522                 :             :  * there too.  Note that sending the cancel directly from the signal handler
     523                 :             :  * is safe because PQcancel() is written to make it so.
     524                 :             :  *
     525                 :             :  * In parallel operation on Unix, each process is responsible for canceling
     526                 :             :  * its own connection (this must be so because nobody else has access to it).
     527                 :             :  * Furthermore, the leader process should attempt to forward its signal to
     528                 :             :  * each child.  In simple manual use of pg_dump/pg_restore, forwarding isn't
     529                 :             :  * needed because typing control-C at the console would deliver SIGINT to
     530                 :             :  * every member of the terminal process group --- but in other scenarios it
     531                 :             :  * might be that only the leader gets signaled.
     532                 :             :  *
     533                 :             :  * On Windows, the cancel handler runs in a separate thread, because that's
     534                 :             :  * how SetConsoleCtrlHandler works.  Because the workers are threads in this
     535                 :             :  * same process, we set a flag (is_cancel_in_progress()) so they stay quiet
     536                 :             :  * about the query cancellations instead of cluttering the screen, then send
     537                 :             :  * cancels on all active connections and return FALSE, which will allow the
     538                 :             :  * process to die.  For safety's sake, we use a critical section to protect
     539                 :             :  * the PGcancel structures against being changed while the signal thread runs.
     540                 :             :  */
     541                 :             : 
     542                 :             : #ifndef WIN32
     543                 :             : 
     544                 :             : /*
     545                 :             :  * Signal handler (Unix only)
     546                 :             :  */
     547                 :             : static void
     548                 :           0 : sigTermHandler(SIGNAL_ARGS)
     549                 :             : {
     550                 :             :     int         i;
     551                 :             :     char        errbuf[1];
     552                 :             : 
     553                 :             :     /*
     554                 :             :      * Some platforms allow delivery of new signals to interrupt an active
     555                 :             :      * signal handler.  That could muck up our attempt to send PQcancel, so
     556                 :             :      * disable the signals that set_cancel_handler enabled.
     557                 :             :      */
     558                 :           0 :     pqsignal(SIGINT, PG_SIG_IGN);
     559                 :           0 :     pqsignal(SIGTERM, PG_SIG_IGN);
     560                 :           0 :     pqsignal(SIGQUIT, PG_SIG_IGN);
     561                 :             : 
     562                 :             :     /*
     563                 :             :      * If we're in the leader, forward signal to all workers.  (It seems best
     564                 :             :      * to do this before PQcancel; killing the leader transaction will result
     565                 :             :      * in invalid-snapshot errors from active workers, which maybe we can
     566                 :             :      * quiet by killing workers first.)  Ignore any errors.
     567                 :             :      */
     568         [ #  # ]:           0 :     if (signal_info.pstate != NULL)
     569                 :             :     {
     570         [ #  # ]:           0 :         for (i = 0; i < signal_info.pstate->numWorkers; i++)
     571                 :             :         {
     572                 :           0 :             pid_t       pid = signal_info.pstate->parallelSlot[i].pid;
     573                 :             : 
     574         [ #  # ]:           0 :             if (pid != 0)
     575                 :           0 :                 kill(pid, SIGTERM);
     576                 :             :         }
     577                 :             :     }
     578                 :             : 
     579                 :             :     /*
     580                 :             :      * Send QueryCancel if we have a connection to send to.  Ignore errors,
     581                 :             :      * there's not much we can do about them anyway.
     582                 :             :      */
     583   [ #  #  #  # ]:           0 :     if (signal_info.myAH != NULL && signal_info.myAH->connCancel != NULL)
     584                 :           0 :         (void) PQcancel(signal_info.myAH->connCancel, errbuf, sizeof(errbuf));
     585                 :             : 
     586                 :             :     /*
     587                 :             :      * Report we're quitting, using nothing more complicated than write(2).
     588                 :             :      * When in parallel operation, only the leader process should do this.
     589                 :             :      */
     590         [ #  # ]:           0 :     if (!signal_info.am_worker)
     591                 :             :     {
     592         [ #  # ]:           0 :         if (progname)
     593                 :             :         {
     594                 :           0 :             write_stderr(progname);
     595                 :           0 :             write_stderr(": ");
     596                 :             :         }
     597                 :           0 :         write_stderr("terminated by user\n");
     598                 :             :     }
     599                 :             : 
     600                 :             :     /*
     601                 :             :      * And die, using _exit() not exit() because the latter will invoke atexit
     602                 :             :      * handlers that can fail if we interrupted related code.
     603                 :             :      */
     604                 :           0 :     _exit(1);
     605                 :             : }
     606                 :             : 
     607                 :             : /*
     608                 :             :  * Enable cancel interrupt handler, if not already done.
     609                 :             :  */
     610                 :             : static void
     611                 :         637 : set_cancel_handler(void)
     612                 :             : {
     613                 :             :     /*
     614                 :             :      * When forking, signal_info.handler_set will propagate into the new
     615                 :             :      * process, but that's fine because the signal handler state does too.
     616                 :             :      */
     617         [ +  + ]:         637 :     if (!signal_info.handler_set)
     618                 :             :     {
     619                 :         244 :         signal_info.handler_set = true;
     620                 :             : 
     621                 :         244 :         pqsignal(SIGINT, sigTermHandler);
     622                 :         244 :         pqsignal(SIGTERM, sigTermHandler);
     623                 :         244 :         pqsignal(SIGQUIT, sigTermHandler);
     624                 :             :     }
     625                 :         637 : }
     626                 :             : 
     627                 :             : #else                           /* WIN32 */
     628                 :             : 
     629                 :             : /*
     630                 :             :  * Console interrupt handler --- runs in a newly-started thread.
     631                 :             :  *
     632                 :             :  * After stopping other threads and sending cancel requests on all open
     633                 :             :  * connections, we return FALSE which will allow the default ExitProcess()
     634                 :             :  * action to be taken.
     635                 :             :  */
     636                 :             : static BOOL WINAPI
     637                 :             : consoleHandler(DWORD dwCtrlType)
     638                 :             : {
     639                 :             :     int         i;
     640                 :             :     char        errbuf[1];
     641                 :             : 
     642                 :             :     if (dwCtrlType == CTRL_C_EVENT ||
     643                 :             :         dwCtrlType == CTRL_BREAK_EVENT)
     644                 :             :     {
     645                 :             :         /*
     646                 :             :          * Tell worker threads to stay quiet about the query cancellations
     647                 :             :          * we're about to send them; otherwise they'd report them as errors
     648                 :             :          * and clutter the user's screen.  This must be set before we send any
     649                 :             :          * cancel, so that a worker is guaranteed to see it by the time its
     650                 :             :          * query fails as a result.
     651                 :             :          */
     652                 :             :         set_cancel_in_progress();
     653                 :             : 
     654                 :             :         /* Critical section prevents changing data we look at here */
     655                 :             :         EnterCriticalSection(&signal_info_lock);
     656                 :             : 
     657                 :             :         /*
     658                 :             :          * If in parallel mode, send QueryCancel to each worker's connected
     659                 :             :          * backend.  Do this before canceling the main transaction, else we
     660                 :             :          * might get invalid-snapshot errors reported before we can stop the
     661                 :             :          * workers.  Ignore errors, there's not much we can do about them
     662                 :             :          * anyway.
     663                 :             :          */
     664                 :             :         if (signal_info.pstate != NULL)
     665                 :             :         {
     666                 :             :             for (i = 0; i < signal_info.pstate->numWorkers; i++)
     667                 :             :             {
     668                 :             :                 ArchiveHandle *AH = signal_info.pstate->parallelSlot[i].AH;
     669                 :             : 
     670                 :             :                 if (AH != NULL && AH->connCancel != NULL)
     671                 :             :                     (void) PQcancel(AH->connCancel, errbuf, sizeof(errbuf));
     672                 :             :             }
     673                 :             :         }
     674                 :             : 
     675                 :             :         /*
     676                 :             :          * Send QueryCancel to leader connection, if enabled.  Ignore errors,
     677                 :             :          * there's not much we can do about them anyway.
     678                 :             :          */
     679                 :             :         if (signal_info.myAH != NULL && signal_info.myAH->connCancel != NULL)
     680                 :             :             (void) PQcancel(signal_info.myAH->connCancel,
     681                 :             :                             errbuf, sizeof(errbuf));
     682                 :             : 
     683                 :             :         LeaveCriticalSection(&signal_info_lock);
     684                 :             : 
     685                 :             :         /*
     686                 :             :          * Report we're quitting, using nothing more complicated than
     687                 :             :          * write(2).  We should be able to use pg_log_*() here, but for now we
     688                 :             :          * stay aligned with the sigTermHandler behavior.
     689                 :             :          */
     690                 :             :         if (progname)
     691                 :             :         {
     692                 :             :             write_stderr(progname);
     693                 :             :             write_stderr(": ");
     694                 :             :         }
     695                 :             :         write_stderr("terminated by user\n");
     696                 :             :     }
     697                 :             : 
     698                 :             :     /* Always return FALSE to allow signal handling to continue */
     699                 :             :     return FALSE;
     700                 :             : }
     701                 :             : 
     702                 :             : /*
     703                 :             :  * Enable cancel interrupt handler, if not already done.
     704                 :             :  */
     705                 :             : static void
     706                 :             : set_cancel_handler(void)
     707                 :             : {
     708                 :             :     if (!signal_info.handler_set)
     709                 :             :     {
     710                 :             :         signal_info.handler_set = true;
     711                 :             : 
     712                 :             :         InitializeCriticalSection(&signal_info_lock);
     713                 :             : 
     714                 :             :         SetConsoleCtrlHandler(consoleHandler, TRUE);
     715                 :             :     }
     716                 :             : }
     717                 :             : 
     718                 :             : #endif                          /* WIN32 */
     719                 :             : 
     720                 :             : 
     721                 :             : /*
     722                 :             :  * set_archive_cancel_info
     723                 :             :  *
     724                 :             :  * Fill AH->connCancel with cancellation info for the specified database
     725                 :             :  * connection; or clear it if conn is NULL.
     726                 :             :  */
     727                 :             : void
     728                 :         637 : set_archive_cancel_info(ArchiveHandle *AH, PGconn *conn)
     729                 :             : {
     730                 :             :     PGcancel   *oldConnCancel;
     731                 :             : 
     732                 :             :     /*
     733                 :             :      * Activate the interrupt handler if we didn't yet in this process.  On
     734                 :             :      * Windows, this also initializes signal_info_lock; therefore it's
     735                 :             :      * important that this happen at least once before we fork off any
     736                 :             :      * threads.
     737                 :             :      */
     738                 :         637 :     set_cancel_handler();
     739                 :             : 
     740                 :             :     /*
     741                 :             :      * On Unix, we assume that storing a pointer value is atomic with respect
     742                 :             :      * to any possible signal interrupt.  On Windows, use a critical section.
     743                 :             :      */
     744                 :             : 
     745                 :             : #ifdef WIN32
     746                 :             :     EnterCriticalSection(&signal_info_lock);
     747                 :             : #endif
     748                 :             : 
     749                 :             :     /* Free the old one if we have one */
     750                 :         637 :     oldConnCancel = AH->connCancel;
     751                 :             :     /* be sure interrupt handler doesn't use pointer while freeing */
     752                 :         637 :     AH->connCancel = NULL;
     753                 :             : 
     754         [ +  + ]:         637 :     if (oldConnCancel != NULL)
     755                 :         347 :         PQfreeCancel(oldConnCancel);
     756                 :             : 
     757                 :             :     /* Set the new one if specified */
     758         [ +  + ]:         637 :     if (conn)
     759                 :         347 :         AH->connCancel = PQgetCancel(conn);
     760                 :             : 
     761                 :             :     /*
     762                 :             :      * On Unix, there's only ever one active ArchiveHandle per process, so we
     763                 :             :      * can just set signal_info.myAH unconditionally.  On Windows, do that
     764                 :             :      * only in the main thread; worker threads have to make sure their
     765                 :             :      * ArchiveHandle appears in the pstate data, which is dealt with in
     766                 :             :      * RunWorker().
     767                 :             :      */
     768                 :             : #ifndef WIN32
     769                 :         637 :     signal_info.myAH = AH;
     770                 :             : #else
     771                 :             :     if (mainThreadId == GetCurrentThreadId())
     772                 :             :         signal_info.myAH = AH;
     773                 :             : #endif
     774                 :             : 
     775                 :             : #ifdef WIN32
     776                 :             :     LeaveCriticalSection(&signal_info_lock);
     777                 :             : #endif
     778                 :         637 : }
     779                 :             : 
     780                 :             : /*
     781                 :             :  * set_cancel_pstate
     782                 :             :  *
     783                 :             :  * Set signal_info.pstate to point to the specified ParallelState, if any.
     784                 :             :  * We need this mainly to have an interlock against Windows signal thread.
     785                 :             :  */
     786                 :             : static void
     787                 :          24 : set_cancel_pstate(ParallelState *pstate)
     788                 :             : {
     789                 :             : #ifdef WIN32
     790                 :             :     EnterCriticalSection(&signal_info_lock);
     791                 :             : #endif
     792                 :             : 
     793                 :          24 :     signal_info.pstate = pstate;
     794                 :             : 
     795                 :             : #ifdef WIN32
     796                 :             :     LeaveCriticalSection(&signal_info_lock);
     797                 :             : #endif
     798                 :          24 : }
     799                 :             : 
     800                 :             : /*
     801                 :             :  * set_cancel_slot_archive
     802                 :             :  *
     803                 :             :  * Set ParallelSlot's AH field to point to the specified archive, if any.
     804                 :             :  * We need this mainly to have an interlock against Windows signal thread.
     805                 :             :  */
     806                 :             : static void
     807                 :          52 : set_cancel_slot_archive(ParallelSlot *slot, ArchiveHandle *AH)
     808                 :             : {
     809                 :             : #ifdef WIN32
     810                 :             :     EnterCriticalSection(&signal_info_lock);
     811                 :             : #endif
     812                 :             : 
     813                 :          52 :     slot->AH = AH;
     814                 :             : 
     815                 :             : #ifdef WIN32
     816                 :             :     LeaveCriticalSection(&signal_info_lock);
     817                 :             : #endif
     818                 :          52 : }
     819                 :             : 
     820                 :             : 
     821                 :             : /*
     822                 :             :  * This function is called by both Unix and Windows variants to set up
     823                 :             :  * and run a worker process.  Caller should exit the process (or thread)
     824                 :             :  * upon return.
     825                 :             :  */
     826                 :             : static void
     827                 :          26 : RunWorker(ArchiveHandle *AH, ParallelSlot *slot)
     828                 :             : {
     829                 :             :     int         pipefd[2];
     830                 :             : 
     831                 :             :     /* fetch child ends of pipes */
     832                 :          26 :     pipefd[PIPE_READ] = slot->pipeRevRead;
     833                 :          26 :     pipefd[PIPE_WRITE] = slot->pipeRevWrite;
     834                 :             : 
     835                 :             :     /*
     836                 :             :      * Clone the archive so that we have our own state to work with, and in
     837                 :             :      * particular our own database connection.
     838                 :             :      *
     839                 :             :      * We clone on Unix as well as Windows, even though technically we don't
     840                 :             :      * need to because fork() gives us a copy in our own address space
     841                 :             :      * already.  But CloneArchive resets the state information and also clones
     842                 :             :      * the database connection which both seem kinda helpful.
     843                 :             :      */
     844                 :          26 :     AH = CloneArchive(AH);
     845                 :             : 
     846                 :             :     /* Remember cloned archive where signal handler can find it */
     847                 :          26 :     set_cancel_slot_archive(slot, AH);
     848                 :             : 
     849                 :             :     /*
     850                 :             :      * Call the setup worker function that's defined in the ArchiveHandle.
     851                 :             :      */
     852                 :          26 :     (AH->SetupWorkerPtr) ((Archive *) AH);
     853                 :             : 
     854                 :             :     /*
     855                 :             :      * Execute commands until done.
     856                 :             :      */
     857                 :          26 :     WaitForCommands(AH, pipefd);
     858                 :             : 
     859                 :             :     /*
     860                 :             :      * Disconnect from database and clean up.
     861                 :             :      */
     862                 :          26 :     set_cancel_slot_archive(slot, NULL);
     863                 :          26 :     DisconnectDatabase(&(AH->public));
     864                 :          26 :     DeCloneArchive(AH);
     865                 :          26 : }
     866                 :             : 
     867                 :             : /*
     868                 :             :  * Thread base function for Windows
     869                 :             :  */
     870                 :             : #ifdef WIN32
     871                 :             : static unsigned __stdcall
     872                 :             : init_spawned_worker_win32(WorkerInfo *wi)
     873                 :             : {
     874                 :             :     ArchiveHandle *AH = wi->AH;
     875                 :             :     ParallelSlot *slot = wi->slot;
     876                 :             : 
     877                 :             :     /* Don't need WorkerInfo anymore */
     878                 :             :     free(wi);
     879                 :             : 
     880                 :             :     /* Run the worker ... */
     881                 :             :     RunWorker(AH, slot);
     882                 :             : 
     883                 :             :     /* Exit the thread */
     884                 :             :     _endthreadex(0);
     885                 :             :     return 0;
     886                 :             : }
     887                 :             : #endif                          /* WIN32 */
     888                 :             : 
     889                 :             : /*
     890                 :             :  * This function starts a parallel dump or restore by spawning off the worker
     891                 :             :  * processes.  For Windows, it creates a number of threads; on Unix the
     892                 :             :  * workers are created with fork().
     893                 :             :  */
     894                 :             : ParallelState *
     895                 :          14 : ParallelBackupStart(ArchiveHandle *AH)
     896                 :             : {
     897                 :             :     ParallelState *pstate;
     898                 :             :     int         i;
     899                 :             : 
     900                 :             :     Assert(AH->public.numWorkers > 0);
     901                 :             : 
     902                 :          14 :     pstate = pg_malloc_object(ParallelState);
     903                 :             : 
     904                 :          14 :     pstate->numWorkers = AH->public.numWorkers;
     905                 :          14 :     pstate->te = NULL;
     906                 :          14 :     pstate->parallelSlot = NULL;
     907                 :             : 
     908         [ +  + ]:          14 :     if (AH->public.numWorkers == 1)
     909                 :           2 :         return pstate;
     910                 :             : 
     911                 :             :     /* Create status arrays, being sure to initialize all fields to 0 */
     912                 :          12 :     pstate->te =
     913                 :          12 :         pg_malloc0_array(TocEntry *, pstate->numWorkers);
     914                 :          12 :     pstate->parallelSlot =
     915                 :          12 :         pg_malloc0_array(ParallelSlot, pstate->numWorkers);
     916                 :             : 
     917                 :             : #ifdef WIN32
     918                 :             :     /* Make fmtId() and fmtQualifiedId() use thread-local storage */
     919                 :             :     getLocalPQExpBuffer = getThreadLocalPQExpBuffer;
     920                 :             : #endif
     921                 :             : 
     922                 :             :     /*
     923                 :             :      * Set the pstate in shutdown_info, to tell the exit handler that it must
     924                 :             :      * clean up workers as well as the main database connection.  But we don't
     925                 :             :      * set this in signal_info yet, because we don't want child processes to
     926                 :             :      * inherit non-NULL signal_info.pstate.
     927                 :             :      */
     928                 :          12 :     shutdown_info.pstate = pstate;
     929                 :             : 
     930                 :             :     /*
     931                 :             :      * Temporarily disable query cancellation on the leader connection.  This
     932                 :             :      * ensures that child processes won't inherit valid AH->connCancel
     933                 :             :      * settings and thus won't try to issue cancels against the leader's
     934                 :             :      * connection.  No harm is done if we fail while it's disabled, because
     935                 :             :      * the leader connection is idle at this point anyway.
     936                 :             :      */
     937                 :          12 :     set_archive_cancel_info(AH, NULL);
     938                 :             : 
     939                 :             :     /* Ensure stdio state is quiesced before forking */
     940                 :          12 :     fflush(NULL);
     941                 :             : 
     942                 :             :     /* Create desired number of workers */
     943         [ +  + ]:          38 :     for (i = 0; i < pstate->numWorkers; i++)
     944                 :             :     {
     945                 :             : #ifdef WIN32
     946                 :             :         WorkerInfo *wi;
     947                 :             :         uintptr_t   handle;
     948                 :             : #else
     949                 :             :         pid_t       pid;
     950                 :             : #endif
     951                 :          26 :         ParallelSlot *slot = &(pstate->parallelSlot[i]);
     952                 :             :         int         pipeMW[2],
     953                 :             :                     pipeWM[2];
     954                 :             : 
     955                 :             :         /* Create communication pipes for this worker */
     956   [ +  -  -  + ]:          26 :         if (pgpipe(pipeMW) < 0 || pgpipe(pipeWM) < 0)
     957                 :           0 :             pg_fatal("could not create communication channels: %m");
     958                 :             : 
     959                 :             :         /* leader's ends of the pipes */
     960                 :          26 :         slot->pipeRead = pipeWM[PIPE_READ];
     961                 :          26 :         slot->pipeWrite = pipeMW[PIPE_WRITE];
     962                 :             :         /* child's ends of the pipes */
     963                 :          26 :         slot->pipeRevRead = pipeMW[PIPE_READ];
     964                 :          26 :         slot->pipeRevWrite = pipeWM[PIPE_WRITE];
     965                 :             : 
     966                 :             : #ifdef WIN32
     967                 :             :         /* Create transient structure to pass args to worker function */
     968                 :             :         wi = pg_malloc_object(WorkerInfo);
     969                 :             : 
     970                 :             :         wi->AH = AH;
     971                 :             :         wi->slot = slot;
     972                 :             : 
     973                 :             :         handle = _beginthreadex(NULL, 0, (void *) &init_spawned_worker_win32,
     974                 :             :                                 wi, 0, &(slot->threadId));
     975                 :             :         if (handle == 0)
     976                 :             :             pg_fatal("could not create worker thread: %m");
     977                 :             :         slot->hThread = handle;
     978                 :             :         slot->workerStatus = WRKR_IDLE;
     979                 :             : #else                           /* !WIN32 */
     980                 :          26 :         pid = fork();
     981         [ +  + ]:          52 :         if (pid == 0)
     982                 :             :         {
     983                 :             :             /* we are the worker */
     984                 :             :             int         j;
     985                 :             : 
     986                 :             :             /* this is needed for GetMyPSlot() */
     987                 :          26 :             slot->pid = getpid();
     988                 :             : 
     989                 :             :             /* instruct signal handler that we're in a worker now */
     990                 :          26 :             signal_info.am_worker = true;
     991                 :             : 
     992                 :             :             /* close read end of Worker -> Leader */
     993                 :          26 :             closesocket(pipeWM[PIPE_READ]);
     994                 :             :             /* close write end of Leader -> Worker */
     995                 :          26 :             closesocket(pipeMW[PIPE_WRITE]);
     996                 :             : 
     997                 :             :             /*
     998                 :             :              * Close all inherited fds for communication of the leader with
     999                 :             :              * previously-forked workers.
    1000                 :             :              */
    1001         [ +  + ]:          42 :             for (j = 0; j < i; j++)
    1002                 :             :             {
    1003                 :          16 :                 closesocket(pstate->parallelSlot[j].pipeRead);
    1004                 :          16 :                 closesocket(pstate->parallelSlot[j].pipeWrite);
    1005                 :             :             }
    1006                 :             : 
    1007                 :             :             /* Run the worker ... */
    1008                 :          26 :             RunWorker(AH, slot);
    1009                 :             : 
    1010                 :             :             /* We can just exit(0) when done */
    1011                 :          26 :             exit(0);
    1012                 :             :         }
    1013         [ -  + ]:          26 :         else if (pid < 0)
    1014                 :             :         {
    1015                 :             :             /* fork failed */
    1016                 :           0 :             pg_fatal("could not create worker process: %m");
    1017                 :             :         }
    1018                 :             : 
    1019                 :             :         /* In Leader after successful fork */
    1020                 :          26 :         slot->pid = pid;
    1021                 :          26 :         slot->workerStatus = WRKR_IDLE;
    1022                 :             : 
    1023                 :             :         /* close read end of Leader -> Worker */
    1024                 :          26 :         closesocket(pipeMW[PIPE_READ]);
    1025                 :             :         /* close write end of Worker -> Leader */
    1026                 :          26 :         closesocket(pipeWM[PIPE_WRITE]);
    1027                 :             : #endif                          /* WIN32 */
    1028                 :             :     }
    1029                 :             : 
    1030                 :             :     /*
    1031                 :             :      * Having forked off the workers, disable SIGPIPE so that leader isn't
    1032                 :             :      * killed if it tries to send a command to a dead worker.  We don't want
    1033                 :             :      * the workers to inherit this setting, though.
    1034                 :             :      */
    1035                 :             : #ifndef WIN32
    1036                 :          12 :     pqsignal(SIGPIPE, PG_SIG_IGN);
    1037                 :             : #endif
    1038                 :             : 
    1039                 :             :     /*
    1040                 :             :      * Re-establish query cancellation on the leader connection.
    1041                 :             :      */
    1042                 :          12 :     set_archive_cancel_info(AH, AH->connection);
    1043                 :             : 
    1044                 :             :     /*
    1045                 :             :      * Tell the cancel signal handler to forward signals to worker processes,
    1046                 :             :      * too.  (As with query cancel, we did not need this earlier because the
    1047                 :             :      * workers have not yet been given anything to do; if we die before this
    1048                 :             :      * point, any already-started workers will see EOF and quit promptly.)
    1049                 :             :      */
    1050                 :          12 :     set_cancel_pstate(pstate);
    1051                 :             : 
    1052                 :          12 :     return pstate;
    1053                 :             : }
    1054                 :             : 
    1055                 :             : /*
    1056                 :             :  * Close down a parallel dump or restore.
    1057                 :             :  */
    1058                 :             : void
    1059                 :          14 : ParallelBackupEnd(ArchiveHandle *AH, ParallelState *pstate)
    1060                 :             : {
    1061                 :             :     int         i;
    1062                 :             : 
    1063                 :             :     /* No work if non-parallel */
    1064         [ +  + ]:          14 :     if (pstate->numWorkers == 1)
    1065                 :           2 :         return;
    1066                 :             : 
    1067                 :             :     /* There should not be any unfinished jobs */
    1068                 :             :     Assert(IsEveryWorkerIdle(pstate));
    1069                 :             : 
    1070                 :             :     /* Close the sockets so that the workers know they can exit */
    1071         [ +  + ]:          38 :     for (i = 0; i < pstate->numWorkers; i++)
    1072                 :             :     {
    1073                 :          26 :         closesocket(pstate->parallelSlot[i].pipeRead);
    1074                 :          26 :         closesocket(pstate->parallelSlot[i].pipeWrite);
    1075                 :             :     }
    1076                 :             : 
    1077                 :             :     /* Wait for them to exit */
    1078                 :          12 :     WaitForTerminatingWorkers(pstate);
    1079                 :             : 
    1080                 :             :     /*
    1081                 :             :      * Unlink pstate from shutdown_info, so the exit handler will not try to
    1082                 :             :      * use it; and likewise unlink from signal_info.
    1083                 :             :      */
    1084                 :          12 :     shutdown_info.pstate = NULL;
    1085                 :          12 :     set_cancel_pstate(NULL);
    1086                 :             : 
    1087                 :             :     /* Release state (mere neatnik-ism, since we're about to terminate) */
    1088                 :          12 :     free(pstate->te);
    1089                 :          12 :     free(pstate->parallelSlot);
    1090                 :          12 :     free(pstate);
    1091                 :             : }
    1092                 :             : 
    1093                 :             : /*
    1094                 :             :  * These next four functions handle construction and parsing of the command
    1095                 :             :  * strings and response strings for parallel workers.
    1096                 :             :  *
    1097                 :             :  * Currently, these can be the same regardless of which archive format we are
    1098                 :             :  * processing.  In future, we might want to let format modules override these
    1099                 :             :  * functions to add format-specific data to a command or response.
    1100                 :             :  */
    1101                 :             : 
    1102                 :             : /*
    1103                 :             :  * buildWorkerCommand: format a command string to send to a worker.
    1104                 :             :  *
    1105                 :             :  * The string is built in the caller-supplied buffer of size buflen.
    1106                 :             :  */
    1107                 :             : static void
    1108                 :         115 : buildWorkerCommand(ArchiveHandle *AH, TocEntry *te, T_Action act,
    1109                 :             :                    char *buf, int buflen)
    1110                 :             : {
    1111         [ +  + ]:         115 :     if (act == ACT_DUMP)
    1112                 :          69 :         snprintf(buf, buflen, "DUMP %d", te->dumpId);
    1113         [ +  - ]:          46 :     else if (act == ACT_RESTORE)
    1114                 :          46 :         snprintf(buf, buflen, "RESTORE %d", te->dumpId);
    1115                 :             :     else
    1116                 :             :         Assert(false);
    1117                 :         115 : }
    1118                 :             : 
    1119                 :             : /*
    1120                 :             :  * parseWorkerCommand: interpret a command string in a worker.
    1121                 :             :  */
    1122                 :             : static void
    1123                 :         115 : parseWorkerCommand(ArchiveHandle *AH, TocEntry **te, T_Action *act,
    1124                 :             :                    const char *msg)
    1125                 :             : {
    1126                 :             :     DumpId      dumpId;
    1127                 :             :     int         nBytes;
    1128                 :             : 
    1129         [ +  + ]:         115 :     if (messageStartsWith(msg, "DUMP "))
    1130                 :             :     {
    1131                 :          69 :         *act = ACT_DUMP;
    1132                 :          69 :         sscanf(msg, "DUMP %d%n", &dumpId, &nBytes);
    1133                 :             :         Assert(nBytes == strlen(msg));
    1134                 :          69 :         *te = getTocEntryByDumpId(AH, dumpId);
    1135                 :             :         Assert(*te != NULL);
    1136                 :             :     }
    1137         [ +  - ]:          46 :     else if (messageStartsWith(msg, "RESTORE "))
    1138                 :             :     {
    1139                 :          46 :         *act = ACT_RESTORE;
    1140                 :          46 :         sscanf(msg, "RESTORE %d%n", &dumpId, &nBytes);
    1141                 :             :         Assert(nBytes == strlen(msg));
    1142                 :          46 :         *te = getTocEntryByDumpId(AH, dumpId);
    1143                 :             :         Assert(*te != NULL);
    1144                 :             :     }
    1145                 :             :     else
    1146                 :           0 :         pg_fatal("unrecognized command received from leader: \"%s\"",
    1147                 :             :                  msg);
    1148                 :         115 : }
    1149                 :             : 
    1150                 :             : /*
    1151                 :             :  * buildWorkerResponse: format a response string to send to the leader.
    1152                 :             :  *
    1153                 :             :  * The string is built in the caller-supplied buffer of size buflen.
    1154                 :             :  */
    1155                 :             : static void
    1156                 :         115 : buildWorkerResponse(ArchiveHandle *AH, TocEntry *te, T_Action act, int status,
    1157                 :             :                     char *buf, int buflen)
    1158                 :             : {
    1159         [ -  + ]:         115 :     snprintf(buf, buflen, "OK %d %d %d",
    1160                 :             :              te->dumpId,
    1161                 :             :              status,
    1162                 :             :              status == WORKER_IGNORED_ERRORS ? AH->public.n_errors : 0);
    1163                 :         115 : }
    1164                 :             : 
    1165                 :             : /*
    1166                 :             :  * parseWorkerResponse: parse the status message returned by a worker.
    1167                 :             :  *
    1168                 :             :  * Returns the integer status code, and may update fields of AH and/or te.
    1169                 :             :  */
    1170                 :             : static int
    1171                 :         115 : parseWorkerResponse(ArchiveHandle *AH, TocEntry *te,
    1172                 :             :                     const char *msg)
    1173                 :             : {
    1174                 :             :     DumpId      dumpId;
    1175                 :             :     int         nBytes,
    1176                 :             :                 n_errors;
    1177                 :         115 :     int         status = 0;
    1178                 :             : 
    1179         [ +  - ]:         115 :     if (messageStartsWith(msg, "OK "))
    1180                 :             :     {
    1181                 :         115 :         sscanf(msg, "OK %d %d %d%n", &dumpId, &status, &n_errors, &nBytes);
    1182                 :             : 
    1183                 :             :         Assert(dumpId == te->dumpId);
    1184                 :             :         Assert(nBytes == strlen(msg));
    1185                 :             : 
    1186                 :         115 :         AH->public.n_errors += n_errors;
    1187                 :             :     }
    1188                 :             :     else
    1189                 :           0 :         pg_fatal("invalid message received from worker: \"%s\"",
    1190                 :             :                  msg);
    1191                 :             : 
    1192                 :         115 :     return status;
    1193                 :             : }
    1194                 :             : 
    1195                 :             : /*
    1196                 :             :  * Dispatch a job to some free worker.
    1197                 :             :  *
    1198                 :             :  * te is the TocEntry to be processed, act is the action to be taken on it.
    1199                 :             :  * callback is the function to call on completion of the job.
    1200                 :             :  *
    1201                 :             :  * If no worker is currently available, this will block, and previously
    1202                 :             :  * registered callback functions may be called.
    1203                 :             :  */
    1204                 :             : void
    1205                 :         115 : DispatchJobForTocEntry(ArchiveHandle *AH,
    1206                 :             :                        ParallelState *pstate,
    1207                 :             :                        TocEntry *te,
    1208                 :             :                        T_Action act,
    1209                 :             :                        ParallelCompletionPtr callback,
    1210                 :             :                        void *callback_data)
    1211                 :             : {
    1212                 :             :     int         worker;
    1213                 :             :     char        buf[256];
    1214                 :             : 
    1215                 :             :     /* Get a worker, waiting if none are idle */
    1216         [ +  + ]:         169 :     while ((worker = GetIdleWorker(pstate)) == NO_SLOT)
    1217                 :          54 :         WaitForWorkers(AH, pstate, WFW_ONE_IDLE);
    1218                 :             : 
    1219                 :             :     /* Construct and send command string */
    1220                 :         115 :     buildWorkerCommand(AH, te, act, buf, sizeof(buf));
    1221                 :             : 
    1222                 :         115 :     sendMessageToWorker(pstate, worker, buf);
    1223                 :             : 
    1224                 :             :     /* Remember worker is busy, and which TocEntry it's working on */
    1225                 :         115 :     pstate->parallelSlot[worker].workerStatus = WRKR_WORKING;
    1226                 :         115 :     pstate->parallelSlot[worker].callback = callback;
    1227                 :         115 :     pstate->parallelSlot[worker].callback_data = callback_data;
    1228                 :         115 :     pstate->te[worker] = te;
    1229                 :         115 : }
    1230                 :             : 
    1231                 :             : /*
    1232                 :             :  * Find an idle worker and return its slot number.
    1233                 :             :  * Return NO_SLOT if none are idle.
    1234                 :             :  */
    1235                 :             : static int
    1236                 :         244 : GetIdleWorker(ParallelState *pstate)
    1237                 :             : {
    1238                 :             :     int         i;
    1239                 :             : 
    1240         [ +  + ]:         609 :     for (i = 0; i < pstate->numWorkers; i++)
    1241                 :             :     {
    1242         [ +  + ]:         489 :         if (pstate->parallelSlot[i].workerStatus == WRKR_IDLE)
    1243                 :         124 :             return i;
    1244                 :             :     }
    1245                 :         120 :     return NO_SLOT;
    1246                 :             : }
    1247                 :             : 
    1248                 :             : /*
    1249                 :             :  * Return true iff no worker is running.
    1250                 :             :  */
    1251                 :             : static bool
    1252                 :          38 : HasEveryWorkerTerminated(ParallelState *pstate)
    1253                 :             : {
    1254                 :             :     int         i;
    1255                 :             : 
    1256         [ +  + ]:          74 :     for (i = 0; i < pstate->numWorkers; i++)
    1257                 :             :     {
    1258   [ +  +  -  + ]:          62 :         if (WORKER_IS_RUNNING(pstate->parallelSlot[i].workerStatus))
    1259                 :          26 :             return false;
    1260                 :             :     }
    1261                 :          12 :     return true;
    1262                 :             : }
    1263                 :             : 
    1264                 :             : /*
    1265                 :             :  * Return true iff every worker is in the WRKR_IDLE state.
    1266                 :             :  */
    1267                 :             : bool
    1268                 :          43 : IsEveryWorkerIdle(ParallelState *pstate)
    1269                 :             : {
    1270                 :             :     int         i;
    1271                 :             : 
    1272         [ +  + ]:          96 :     for (i = 0; i < pstate->numWorkers; i++)
    1273                 :             :     {
    1274         [ +  + ]:          76 :         if (pstate->parallelSlot[i].workerStatus != WRKR_IDLE)
    1275                 :          23 :             return false;
    1276                 :             :     }
    1277                 :          20 :     return true;
    1278                 :             : }
    1279                 :             : 
    1280                 :             : /*
    1281                 :             :  * Acquire lock on a table to be dumped by a worker process.
    1282                 :             :  *
    1283                 :             :  * The leader process is already holding an ACCESS SHARE lock.  Ordinarily
    1284                 :             :  * it's no problem for a worker to get one too, but if anything else besides
    1285                 :             :  * pg_dump is running, there's a possible deadlock:
    1286                 :             :  *
    1287                 :             :  * 1) Leader dumps the schema and locks all tables in ACCESS SHARE mode.
    1288                 :             :  * 2) Another process requests an ACCESS EXCLUSIVE lock (which is not granted
    1289                 :             :  *    because the leader holds a conflicting ACCESS SHARE lock).
    1290                 :             :  * 3) A worker process also requests an ACCESS SHARE lock to read the table.
    1291                 :             :  *    The worker is enqueued behind the ACCESS EXCLUSIVE lock request.
    1292                 :             :  * 4) Now we have a deadlock, since the leader is effectively waiting for
    1293                 :             :  *    the worker.  The server cannot detect that, however.
    1294                 :             :  *
    1295                 :             :  * To prevent an infinite wait, prior to touching a table in a worker, request
    1296                 :             :  * a lock in ACCESS SHARE mode but with NOWAIT.  If we don't get the lock,
    1297                 :             :  * then we know that somebody else has requested an ACCESS EXCLUSIVE lock and
    1298                 :             :  * so we have a deadlock.  We must fail the backup in that case.
    1299                 :             :  */
    1300                 :             : static void
    1301                 :          69 : lockTableForWorker(ArchiveHandle *AH, TocEntry *te)
    1302                 :             : {
    1303                 :             :     const char *qualId;
    1304                 :             :     PQExpBuffer query;
    1305                 :             :     PGresult   *res;
    1306                 :             : 
    1307                 :             :     /* Nothing to do for BLOBS */
    1308         [ +  + ]:          69 :     if (strcmp(te->desc, "BLOBS") == 0)
    1309                 :           4 :         return;
    1310                 :             : 
    1311                 :          65 :     query = createPQExpBuffer();
    1312                 :             : 
    1313                 :          65 :     qualId = fmtQualifiedId(te->namespace, te->tag);
    1314                 :             : 
    1315                 :          65 :     appendPQExpBuffer(query, "LOCK TABLE %s IN ACCESS SHARE MODE NOWAIT",
    1316                 :             :                       qualId);
    1317                 :             : 
    1318                 :          65 :     res = PQexec(AH->connection, query->data);
    1319                 :             : 
    1320   [ +  -  -  + ]:          65 :     if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
    1321                 :           0 :         pg_fatal("could not obtain lock on relation \"%s\"\n"
    1322                 :             :                  "This usually means that someone requested an ACCESS EXCLUSIVE lock "
    1323                 :             :                  "on the table after the pg_dump parent process had gotten the "
    1324                 :             :                  "initial ACCESS SHARE lock on the table.", qualId);
    1325                 :             : 
    1326                 :          65 :     PQclear(res);
    1327                 :          65 :     destroyPQExpBuffer(query);
    1328                 :             : }
    1329                 :             : 
    1330                 :             : /*
    1331                 :             :  * WaitForCommands: main routine for a worker process.
    1332                 :             :  *
    1333                 :             :  * Read and execute commands from the leader until we see EOF on the pipe.
    1334                 :             :  */
    1335                 :             : static void
    1336                 :          26 : WaitForCommands(ArchiveHandle *AH, int pipefd[2])
    1337                 :             : {
    1338                 :             :     char       *command;
    1339                 :             :     TocEntry   *te;
    1340                 :             :     T_Action    act;
    1341                 :          26 :     int         status = 0;
    1342                 :             :     char        buf[256];
    1343                 :             : 
    1344                 :             :     for (;;)
    1345                 :             :     {
    1346         [ +  + ]:         141 :         if (!(command = getMessageFromLeader(pipefd)))
    1347                 :             :         {
    1348                 :             :             /* EOF, so done */
    1349                 :          26 :             return;
    1350                 :             :         }
    1351                 :             : 
    1352                 :             :         /* Decode the command */
    1353                 :         115 :         parseWorkerCommand(AH, &te, &act, command);
    1354                 :             : 
    1355         [ +  + ]:         115 :         if (act == ACT_DUMP)
    1356                 :             :         {
    1357                 :             :             /* Acquire lock on this table within the worker's session */
    1358                 :          69 :             lockTableForWorker(AH, te);
    1359                 :             : 
    1360                 :             :             /* Perform the dump command */
    1361                 :          69 :             status = (AH->WorkerJobDumpPtr) (AH, te);
    1362                 :             :         }
    1363         [ +  - ]:          46 :         else if (act == ACT_RESTORE)
    1364                 :             :         {
    1365                 :             :             /* Perform the restore command */
    1366                 :          46 :             status = (AH->WorkerJobRestorePtr) (AH, te);
    1367                 :             :         }
    1368                 :             :         else
    1369                 :             :             Assert(false);
    1370                 :             : 
    1371                 :             :         /* Return status to leader */
    1372                 :         115 :         buildWorkerResponse(AH, te, act, status, buf, sizeof(buf));
    1373                 :             : 
    1374                 :         115 :         sendMessageToLeader(pipefd, buf);
    1375                 :             : 
    1376                 :             :         /* command was pg_malloc'd and we are responsible for free()ing it. */
    1377                 :         115 :         free(command);
    1378                 :             :     }
    1379                 :             : }
    1380                 :             : 
    1381                 :             : /*
    1382                 :             :  * Check for status messages from workers.
    1383                 :             :  *
    1384                 :             :  * If do_wait is true, wait to get a status message; otherwise, just return
    1385                 :             :  * immediately if there is none available.
    1386                 :             :  *
    1387                 :             :  * When we get a status message, we pass the status code to the callback
    1388                 :             :  * function that was specified to DispatchJobForTocEntry, then reset the
    1389                 :             :  * worker status to IDLE.
    1390                 :             :  *
    1391                 :             :  * Returns true if we collected a status message, else false.
    1392                 :             :  *
    1393                 :             :  * XXX is it worth checking for more than one status message per call?
    1394                 :             :  * It seems somewhat unlikely that multiple workers would finish at exactly
    1395                 :             :  * the same time.
    1396                 :             :  */
    1397                 :             : static bool
    1398                 :         197 : ListenToWorkers(ArchiveHandle *AH, ParallelState *pstate, bool do_wait)
    1399                 :             : {
    1400                 :             :     int         worker;
    1401                 :             :     char       *msg;
    1402                 :             : 
    1403                 :             :     /* Try to collect a status message */
    1404                 :         197 :     msg = getMessageFromWorker(pstate, do_wait, &worker);
    1405                 :             : 
    1406         [ +  + ]:         197 :     if (!msg)
    1407                 :             :     {
    1408                 :             :         /* If do_wait is true, we must have detected EOF on some socket */
    1409         [ -  + ]:          82 :         if (do_wait)
    1410                 :           0 :             pg_fatal("a worker process died unexpectedly");
    1411                 :          82 :         return false;
    1412                 :             :     }
    1413                 :             : 
    1414                 :             :     /* Process it and update our idea of the worker's status */
    1415         [ +  - ]:         115 :     if (messageStartsWith(msg, "OK "))
    1416                 :             :     {
    1417                 :         115 :         ParallelSlot *slot = &pstate->parallelSlot[worker];
    1418                 :         115 :         TocEntry   *te = pstate->te[worker];
    1419                 :             :         int         status;
    1420                 :             : 
    1421                 :         115 :         status = parseWorkerResponse(AH, te, msg);
    1422                 :         115 :         slot->callback(AH, te, status, slot->callback_data);
    1423                 :         115 :         slot->workerStatus = WRKR_IDLE;
    1424                 :         115 :         pstate->te[worker] = NULL;
    1425                 :             :     }
    1426                 :             :     else
    1427                 :           0 :         pg_fatal("invalid message received from worker: \"%s\"",
    1428                 :             :                  msg);
    1429                 :             : 
    1430                 :             :     /* Free the string returned from getMessageFromWorker */
    1431                 :         115 :     free(msg);
    1432                 :             : 
    1433                 :         115 :     return true;
    1434                 :             : }
    1435                 :             : 
    1436                 :             : /*
    1437                 :             :  * Check for status results from workers, waiting if necessary.
    1438                 :             :  *
    1439                 :             :  * Available wait modes are:
    1440                 :             :  * WFW_NO_WAIT: reap any available status, but don't block
    1441                 :             :  * WFW_GOT_STATUS: wait for at least one more worker to finish
    1442                 :             :  * WFW_ONE_IDLE: wait for at least one worker to be idle
    1443                 :             :  * WFW_ALL_IDLE: wait for all workers to be idle
    1444                 :             :  *
    1445                 :             :  * Any received results are passed to the callback specified to
    1446                 :             :  * DispatchJobForTocEntry.
    1447                 :             :  *
    1448                 :             :  * This function is executed in the leader process.
    1449                 :             :  */
    1450                 :             : void
    1451                 :         117 : WaitForWorkers(ArchiveHandle *AH, ParallelState *pstate, WFW_WaitOption mode)
    1452                 :             : {
    1453                 :         117 :     bool        do_wait = false;
    1454                 :             : 
    1455                 :             :     /*
    1456                 :             :      * In GOT_STATUS mode, always block waiting for a message, since we can't
    1457                 :             :      * return till we get something.  In other modes, we don't block the first
    1458                 :             :      * time through the loop.
    1459                 :             :      */
    1460         [ +  + ]:         117 :     if (mode == WFW_GOT_STATUS)
    1461                 :             :     {
    1462                 :             :         /* Assert that caller knows what it's doing */
    1463                 :             :         Assert(!IsEveryWorkerIdle(pstate));
    1464                 :           9 :         do_wait = true;
    1465                 :             :     }
    1466                 :             : 
    1467                 :             :     for (;;)
    1468                 :             :     {
    1469                 :             :         /*
    1470                 :             :          * Check for status messages, even if we don't need to block.  We do
    1471                 :             :          * not try very hard to reap all available messages, though, since
    1472                 :             :          * there's unlikely to be more than one.
    1473                 :             :          */
    1474         [ +  + ]:         197 :         if (ListenToWorkers(AH, pstate, do_wait))
    1475                 :             :         {
    1476                 :             :             /*
    1477                 :             :              * If we got a message, we are done by definition for GOT_STATUS
    1478                 :             :              * mode, and we can also be certain that there's at least one idle
    1479                 :             :              * worker.  So we're done in all but ALL_IDLE mode.
    1480                 :             :              */
    1481         [ +  + ]:         115 :             if (mode != WFW_ALL_IDLE)
    1482                 :         100 :                 return;
    1483                 :             :         }
    1484                 :             : 
    1485                 :             :         /* Check whether we must wait for new status messages */
    1486   [ -  -  +  +  :          97 :         switch (mode)
                      - ]
    1487                 :             :         {
    1488                 :           0 :             case WFW_NO_WAIT:
    1489                 :           0 :                 return;         /* never wait */
    1490                 :           0 :             case WFW_GOT_STATUS:
    1491                 :             :                 Assert(false);  /* can't get here, because we waited */
    1492                 :           0 :                 break;
    1493                 :          75 :             case WFW_ONE_IDLE:
    1494         [ +  + ]:          75 :                 if (GetIdleWorker(pstate) != NO_SLOT)
    1495                 :           9 :                     return;
    1496                 :          66 :                 break;
    1497                 :          22 :             case WFW_ALL_IDLE:
    1498         [ +  + ]:          22 :                 if (IsEveryWorkerIdle(pstate))
    1499                 :           8 :                     return;
    1500                 :          14 :                 break;
    1501                 :             :         }
    1502                 :             : 
    1503                 :             :         /* Loop back, and this time wait for something to happen */
    1504                 :          80 :         do_wait = true;
    1505                 :             :     }
    1506                 :             : }
    1507                 :             : 
    1508                 :             : /*
    1509                 :             :  * Read one command message from the leader, blocking if necessary
    1510                 :             :  * until one is available, and return it as a malloc'd string.
    1511                 :             :  * On EOF, return NULL.
    1512                 :             :  *
    1513                 :             :  * This function is executed in worker processes.
    1514                 :             :  */
    1515                 :             : static char *
    1516                 :         141 : getMessageFromLeader(int pipefd[2])
    1517                 :             : {
    1518                 :         141 :     return readMessageFromPipe(pipefd[PIPE_READ]);
    1519                 :             : }
    1520                 :             : 
    1521                 :             : /*
    1522                 :             :  * Send a status message to the leader.
    1523                 :             :  *
    1524                 :             :  * This function is executed in worker processes.
    1525                 :             :  */
    1526                 :             : static void
    1527                 :         115 : sendMessageToLeader(int pipefd[2], const char *str)
    1528                 :             : {
    1529                 :         115 :     int         len = strlen(str) + 1;
    1530                 :             : 
    1531         [ -  + ]:         115 :     if (pipewrite(pipefd[PIPE_WRITE], str, len) != len)
    1532                 :           0 :         pg_fatal("could not write to the communication channel: %m");
    1533                 :         115 : }
    1534                 :             : 
    1535                 :             : /*
    1536                 :             :  * Wait until some descriptor in "workerset" becomes readable.
    1537                 :             :  * Returns -1 on error, else the number of readable descriptors.
    1538                 :             :  */
    1539                 :             : static int
    1540                 :          89 : select_loop(int maxFd, fd_set *workerset)
    1541                 :             : {
    1542                 :             :     int         i;
    1543                 :          89 :     fd_set      saveSet = *workerset;
    1544                 :             : 
    1545                 :             :     for (;;)
    1546                 :             :     {
    1547                 :          89 :         *workerset = saveSet;
    1548                 :          89 :         i = select(maxFd + 1, workerset, NULL, NULL, NULL);
    1549                 :             : 
    1550                 :             : #ifndef WIN32
    1551   [ -  +  -  - ]:          89 :         if (i < 0 && errno == EINTR)
    1552                 :           0 :             continue;
    1553                 :             : #else
    1554                 :             :         if (i == SOCKET_ERROR && WSAGetLastError() == WSAEINTR)
    1555                 :             :             continue;
    1556                 :             : #endif
    1557                 :          89 :         break;
    1558                 :             :     }
    1559                 :             : 
    1560                 :          89 :     return i;
    1561                 :             : }
    1562                 :             : 
    1563                 :             : 
    1564                 :             : /*
    1565                 :             :  * Check for messages from worker processes.
    1566                 :             :  *
    1567                 :             :  * If a message is available, return it as a malloc'd string, and put the
    1568                 :             :  * index of the sending worker in *worker.
    1569                 :             :  *
    1570                 :             :  * If nothing is available, wait if "do_wait" is true, else return NULL.
    1571                 :             :  *
    1572                 :             :  * If we detect EOF on any socket, we'll return NULL.  It's not great that
    1573                 :             :  * that's hard to distinguish from the no-data-available case, but for now
    1574                 :             :  * our one caller is okay with that.
    1575                 :             :  *
    1576                 :             :  * This function is executed in the leader process.
    1577                 :             :  */
    1578                 :             : static char *
    1579                 :         197 : getMessageFromWorker(ParallelState *pstate, bool do_wait, int *worker)
    1580                 :             : {
    1581                 :             :     int         i;
    1582                 :             :     fd_set      workerset;
    1583                 :         197 :     int         maxFd = -1;
    1584                 :         197 :     struct timeval nowait = {0, 0};
    1585                 :             : 
    1586                 :             :     /* construct bitmap of socket descriptors for select() */
    1587         [ +  + ]:        3349 :     FD_ZERO(&workerset);
    1588         [ +  + ]:         669 :     for (i = 0; i < pstate->numWorkers; i++)
    1589                 :             :     {
    1590   [ +  +  -  + ]:         472 :         if (!WORKER_IS_RUNNING(pstate->parallelSlot[i].workerStatus))
    1591                 :           0 :             continue;
    1592                 :         472 :         FD_SET(pstate->parallelSlot[i].pipeRead, &workerset);
    1593         [ +  - ]:         472 :         if (pstate->parallelSlot[i].pipeRead > maxFd)
    1594                 :         472 :             maxFd = pstate->parallelSlot[i].pipeRead;
    1595                 :             :     }
    1596                 :             : 
    1597         [ +  + ]:         197 :     if (do_wait)
    1598                 :             :     {
    1599                 :          89 :         i = select_loop(maxFd, &workerset);
    1600                 :             :         Assert(i != 0);
    1601                 :             :     }
    1602                 :             :     else
    1603                 :             :     {
    1604         [ +  + ]:         108 :         if ((i = select(maxFd + 1, &workerset, NULL, NULL, &nowait)) == 0)
    1605                 :          82 :             return NULL;
    1606                 :             :     }
    1607                 :             : 
    1608         [ -  + ]:         115 :     if (i < 0)
    1609                 :           0 :         pg_fatal("%s() failed: %m", "select");
    1610                 :             : 
    1611         [ +  - ]:         200 :     for (i = 0; i < pstate->numWorkers; i++)
    1612                 :             :     {
    1613                 :             :         char       *msg;
    1614                 :             : 
    1615   [ +  +  -  + ]:         200 :         if (!WORKER_IS_RUNNING(pstate->parallelSlot[i].workerStatus))
    1616                 :           0 :             continue;
    1617         [ +  + ]:         200 :         if (!FD_ISSET(pstate->parallelSlot[i].pipeRead, &workerset))
    1618                 :          85 :             continue;
    1619                 :             : 
    1620                 :             :         /*
    1621                 :             :          * Read the message if any.  If the socket is ready because of EOF,
    1622                 :             :          * we'll return NULL instead (and the socket will stay ready, so the
    1623                 :             :          * condition will persist).
    1624                 :             :          *
    1625                 :             :          * Note: because this is a blocking read, we'll wait if only part of
    1626                 :             :          * the message is available.  Waiting a long time would be bad, but
    1627                 :             :          * since worker status messages are short and are always sent in one
    1628                 :             :          * operation, it shouldn't be a problem in practice.
    1629                 :             :          */
    1630                 :         115 :         msg = readMessageFromPipe(pstate->parallelSlot[i].pipeRead);
    1631                 :         115 :         *worker = i;
    1632                 :         115 :         return msg;
    1633                 :             :     }
    1634                 :             :     Assert(false);
    1635                 :           0 :     return NULL;
    1636                 :             : }
    1637                 :             : 
    1638                 :             : /*
    1639                 :             :  * Send a command message to the specified worker process.
    1640                 :             :  *
    1641                 :             :  * This function is executed in the leader process.
    1642                 :             :  */
    1643                 :             : static void
    1644                 :         115 : sendMessageToWorker(ParallelState *pstate, int worker, const char *str)
    1645                 :             : {
    1646                 :         115 :     int         len = strlen(str) + 1;
    1647                 :             : 
    1648         [ -  + ]:         115 :     if (pipewrite(pstate->parallelSlot[worker].pipeWrite, str, len) != len)
    1649                 :             :     {
    1650                 :           0 :         pg_fatal("could not write to the communication channel: %m");
    1651                 :             :     }
    1652                 :         115 : }
    1653                 :             : 
    1654                 :             : /*
    1655                 :             :  * Read one message from the specified pipe (fd), blocking if necessary
    1656                 :             :  * until one is available, and return it as a malloc'd string.
    1657                 :             :  * On EOF, return NULL.
    1658                 :             :  *
    1659                 :             :  * A "message" on the channel is just a null-terminated string.
    1660                 :             :  */
    1661                 :             : static char *
    1662                 :         256 : readMessageFromPipe(int fd)
    1663                 :             : {
    1664                 :             :     char       *msg;
    1665                 :             :     int         msgsize,
    1666                 :             :                 bufsize;
    1667                 :             :     int         ret;
    1668                 :             : 
    1669                 :             :     /*
    1670                 :             :      * In theory, if we let piperead() read multiple bytes, it might give us
    1671                 :             :      * back fragments of multiple messages.  (That can't actually occur, since
    1672                 :             :      * neither leader nor workers send more than one message without waiting
    1673                 :             :      * for a reply, but we don't wish to assume that here.)  For simplicity,
    1674                 :             :      * read a byte at a time until we get the terminating '\0'.  This method
    1675                 :             :      * is a bit inefficient, but since this is only used for relatively short
    1676                 :             :      * command and status strings, it shouldn't matter.
    1677                 :             :      */
    1678                 :         256 :     bufsize = 64;               /* could be any number */
    1679                 :         256 :     msg = (char *) pg_malloc(bufsize);
    1680                 :         256 :     msgsize = 0;
    1681                 :             :     for (;;)
    1682                 :             :     {
    1683                 :        2438 :         Assert(msgsize < bufsize);
    1684                 :        2694 :         ret = piperead(fd, msg + msgsize, 1);
    1685         [ +  + ]:        2694 :         if (ret <= 0)
    1686                 :          26 :             break;              /* error or connection closure */
    1687                 :             : 
    1688                 :             :         Assert(ret == 1);
    1689                 :             : 
    1690         [ +  + ]:        2668 :         if (msg[msgsize] == '\0')
    1691                 :         230 :             return msg;         /* collected whole message */
    1692                 :             : 
    1693                 :        2438 :         msgsize++;
    1694         [ -  + ]:        2438 :         if (msgsize == bufsize) /* enlarge buffer if needed */
    1695                 :             :         {
    1696                 :           0 :             bufsize += 16;      /* could be any number */
    1697                 :           0 :             msg = (char *) pg_realloc(msg, bufsize);
    1698                 :             :         }
    1699                 :             :     }
    1700                 :             : 
    1701                 :             :     /* Other end has closed the connection */
    1702                 :          26 :     pg_free(msg);
    1703                 :          26 :     return NULL;
    1704                 :             : }
    1705                 :             : 
    1706                 :             : #ifdef WIN32
    1707                 :             : 
    1708                 :             : /*
    1709                 :             :  * This is a replacement version of pipe(2) for Windows which allows the pipe
    1710                 :             :  * handles to be used in select().
    1711                 :             :  *
    1712                 :             :  * Reads and writes on the pipe must go through piperead()/pipewrite().
    1713                 :             :  *
    1714                 :             :  * For consistency with Unix we declare the returned handles as "int".
    1715                 :             :  * This is okay even on WIN64 because system handles are not more than
    1716                 :             :  * 32 bits wide, but we do have to do some casting.
    1717                 :             :  */
    1718                 :             : static int
    1719                 :             : pgpipe(int handles[2])
    1720                 :             : {
    1721                 :             :     pgsocket    s,
    1722                 :             :                 tmp_sock;
    1723                 :             :     struct sockaddr_in serv_addr;
    1724                 :             :     int         len = sizeof(serv_addr);
    1725                 :             : 
    1726                 :             :     /* We have to use the Unix socket invalid file descriptor value here. */
    1727                 :             :     handles[0] = handles[1] = -1;
    1728                 :             : 
    1729                 :             :     /*
    1730                 :             :      * setup listen socket
    1731                 :             :      */
    1732                 :             :     if ((s = socket(AF_INET, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
    1733                 :             :     {
    1734                 :             :         pg_log_error("pgpipe: could not create socket: error code %d",
    1735                 :             :                      WSAGetLastError());
    1736                 :             :         return -1;
    1737                 :             :     }
    1738                 :             : 
    1739                 :             :     memset(&serv_addr, 0, sizeof(serv_addr));
    1740                 :             :     serv_addr.sin_family = AF_INET;
    1741                 :             :     serv_addr.sin_port = pg_hton16(0);
    1742                 :             :     serv_addr.sin_addr.s_addr = pg_hton32(INADDR_LOOPBACK);
    1743                 :             :     if (bind(s, (SOCKADDR *) &serv_addr, len) == SOCKET_ERROR)
    1744                 :             :     {
    1745                 :             :         pg_log_error("pgpipe: could not bind: error code %d",
    1746                 :             :                      WSAGetLastError());
    1747                 :             :         closesocket(s);
    1748                 :             :         return -1;
    1749                 :             :     }
    1750                 :             :     if (listen(s, 1) == SOCKET_ERROR)
    1751                 :             :     {
    1752                 :             :         pg_log_error("pgpipe: could not listen: error code %d",
    1753                 :             :                      WSAGetLastError());
    1754                 :             :         closesocket(s);
    1755                 :             :         return -1;
    1756                 :             :     }
    1757                 :             :     if (getsockname(s, (SOCKADDR *) &serv_addr, &len) == SOCKET_ERROR)
    1758                 :             :     {
    1759                 :             :         pg_log_error("pgpipe: %s() failed: error code %d", "getsockname",
    1760                 :             :                      WSAGetLastError());
    1761                 :             :         closesocket(s);
    1762                 :             :         return -1;
    1763                 :             :     }
    1764                 :             : 
    1765                 :             :     /*
    1766                 :             :      * setup pipe handles
    1767                 :             :      */
    1768                 :             :     if ((tmp_sock = socket(AF_INET, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
    1769                 :             :     {
    1770                 :             :         pg_log_error("pgpipe: could not create second socket: error code %d",
    1771                 :             :                      WSAGetLastError());
    1772                 :             :         closesocket(s);
    1773                 :             :         return -1;
    1774                 :             :     }
    1775                 :             :     handles[1] = (int) tmp_sock;
    1776                 :             : 
    1777                 :             :     if (connect(handles[1], (SOCKADDR *) &serv_addr, len) == SOCKET_ERROR)
    1778                 :             :     {
    1779                 :             :         pg_log_error("pgpipe: could not connect socket: error code %d",
    1780                 :             :                      WSAGetLastError());
    1781                 :             :         closesocket(handles[1]);
    1782                 :             :         handles[1] = -1;
    1783                 :             :         closesocket(s);
    1784                 :             :         return -1;
    1785                 :             :     }
    1786                 :             :     if ((tmp_sock = accept(s, (SOCKADDR *) &serv_addr, &len)) == PGINVALID_SOCKET)
    1787                 :             :     {
    1788                 :             :         pg_log_error("pgpipe: could not accept connection: error code %d",
    1789                 :             :                      WSAGetLastError());
    1790                 :             :         closesocket(handles[1]);
    1791                 :             :         handles[1] = -1;
    1792                 :             :         closesocket(s);
    1793                 :             :         return -1;
    1794                 :             :     }
    1795                 :             :     handles[0] = (int) tmp_sock;
    1796                 :             : 
    1797                 :             :     closesocket(s);
    1798                 :             :     return 0;
    1799                 :             : }
    1800                 :             : 
    1801                 :             : #endif                          /* WIN32 */
        

Generated by: LCOV version 2.0-1