Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * auxprocess.c 3 : * functions related to auxiliary processes. 4 : * 5 : * 6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group 7 : * Portions Copyright (c) 1994, Regents of the University of California 8 : * 9 : * IDENTIFICATION 10 : * src/backend/postmaster/auxprocess.c 11 : *------------------------------------------------------------------------- 12 : */ 13 : #include "postgres.h" 14 : 15 : #include <unistd.h> 16 : #include <signal.h> 17 : 18 : #include "libpq/pqsignal.h" 19 : #include "miscadmin.h" 20 : #include "pgstat.h" 21 : #include "postmaster/auxprocess.h" 22 : #include "postmaster/bgwriter.h" 23 : #include "postmaster/startup.h" 24 : #include "postmaster/walwriter.h" 25 : #include "replication/walreceiver.h" 26 : #include "storage/bufmgr.h" 27 : #include "storage/bufpage.h" 28 : #include "storage/condition_variable.h" 29 : #include "storage/ipc.h" 30 : #include "storage/proc.h" 31 : #include "tcop/tcopprot.h" 32 : #include "utils/memutils.h" 33 : #include "utils/ps_status.h" 34 : #include "utils/rel.h" 35 : 36 : 37 : static void ShutdownAuxiliaryProcess(int code, Datum arg); 38 : 39 : 40 : /* ---------------- 41 : * global variables 42 : * ---------------- 43 : */ 44 : 45 : AuxProcType MyAuxProcType = NotAnAuxProcess; /* declared in miscadmin.h */ 46 : 47 : 48 : /* 49 : * AuxiliaryProcessMain 50 : * 51 : * The main entry point for auxiliary processes, such as the bgwriter, 52 : * walwriter, walreceiver, bootstrapper and the shared memory checker code. 53 : * 54 : * This code is here just because of historical reasons. 55 : */ 56 : void 57 3726 : AuxiliaryProcessMain(AuxProcType auxtype) 58 : { 59 : Assert(IsUnderPostmaster); 60 : 61 3726 : MyAuxProcType = auxtype; 62 : 63 3726 : switch (MyAuxProcType) 64 : { 65 1202 : case StartupProcess: 66 1202 : MyBackendType = B_STARTUP; 67 1202 : break; 68 24 : case ArchiverProcess: 69 24 : MyBackendType = B_ARCHIVER; 70 24 : break; 71 740 : case BgWriterProcess: 72 740 : MyBackendType = B_BG_WRITER; 73 740 : break; 74 740 : case CheckpointerProcess: 75 740 : MyBackendType = B_CHECKPOINTER; 76 740 : break; 77 678 : case WalWriterProcess: 78 678 : MyBackendType = B_WAL_WRITER; 79 678 : break; 80 342 : case WalReceiverProcess: 81 342 : MyBackendType = B_WAL_RECEIVER; 82 342 : break; 83 0 : default: 84 0 : elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType); 85 : MyBackendType = B_INVALID; 86 : } 87 : 88 3726 : init_ps_display(NULL); 89 : 90 3726 : SetProcessingMode(BootstrapProcessing); 91 3726 : IgnoreSystemIndexes = true; 92 : 93 : /* 94 : * As an auxiliary process, we aren't going to do the full InitPostgres 95 : * pushups, but there are a couple of things that need to get lit up even 96 : * in an auxiliary process. 97 : */ 98 : 99 : /* 100 : * Create a PGPROC so we can use LWLocks and access shared memory. 101 : */ 102 3726 : InitAuxiliaryProcess(); 103 : 104 3726 : BaseInit(); 105 : 106 : /* 107 : * Assign the ProcSignalSlot for an auxiliary process. Since it doesn't 108 : * have a BackendId, the slot is statically allocated based on the 109 : * auxiliary process type (MyAuxProcType). Backends use slots indexed in 110 : * the range from 1 to MaxBackends (inclusive), so we use MaxBackends + 111 : * AuxProcType + 1 as the index of the slot for an auxiliary process. 112 : * 113 : * This will need rethinking if we ever want more than one of a particular 114 : * auxiliary process type. 115 : */ 116 3726 : ProcSignalInit(MaxBackends + MyAuxProcType + 1); 117 : 118 : /* 119 : * Auxiliary processes don't run transactions, but they may need a 120 : * resource owner anyway to manage buffer pins acquired outside 121 : * transactions (and, perhaps, other things in future). 122 : */ 123 3726 : CreateAuxProcessResourceOwner(); 124 : 125 : 126 : /* Initialize backend status information */ 127 3726 : pgstat_beinit(); 128 3726 : pgstat_bestart(); 129 : 130 : /* register a before-shutdown callback for LWLock cleanup */ 131 3726 : before_shmem_exit(ShutdownAuxiliaryProcess, 0); 132 : 133 3726 : SetProcessingMode(NormalProcessing); 134 : 135 3726 : switch (MyAuxProcType) 136 : { 137 1202 : case StartupProcess: 138 1202 : StartupProcessMain(); 139 : proc_exit(1); 140 : 141 24 : case ArchiverProcess: 142 24 : PgArchiverMain(); 143 : proc_exit(1); 144 : 145 740 : case BgWriterProcess: 146 740 : BackgroundWriterMain(); 147 : proc_exit(1); 148 : 149 740 : case CheckpointerProcess: 150 740 : CheckpointerMain(); 151 : proc_exit(1); 152 : 153 678 : case WalWriterProcess: 154 678 : WalWriterMain(); 155 : proc_exit(1); 156 : 157 342 : case WalReceiverProcess: 158 342 : WalReceiverMain(); 159 : proc_exit(1); 160 : 161 0 : default: 162 0 : elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType); 163 : proc_exit(1); 164 : } 165 : } 166 : 167 : /* 168 : * Begin shutdown of an auxiliary process. This is approximately the equivalent 169 : * of ShutdownPostgres() in postinit.c. We can't run transactions in an 170 : * auxiliary process, so most of the work of AbortTransaction() is not needed, 171 : * but we do need to make sure we've released any LWLocks we are holding. 172 : * (This is only critical during an error exit.) 173 : */ 174 : static void 175 3726 : ShutdownAuxiliaryProcess(int code, Datum arg) 176 : { 177 3726 : LWLockReleaseAll(); 178 3726 : ConditionVariableCancelSleep(); 179 3726 : pgstat_report_wait_end(); 180 3726 : }