Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include <signal.h>
00018 #include <unistd.h>
00019
00020 #include "commands/async.h"
00021 #include "miscadmin.h"
00022 #include "storage/latch.h"
00023 #include "storage/ipc.h"
00024 #include "storage/shmem.h"
00025 #include "storage/sinval.h"
00026 #include "tcop/tcopprot.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 typedef struct
00048 {
00049 pid_t pss_pid;
00050 sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS];
00051 } ProcSignalSlot;
00052
00053
00054
00055
00056
00057
00058 #define NumProcSignalSlots (MaxBackends + NUM_AUXPROCTYPES)
00059
00060 static ProcSignalSlot *ProcSignalSlots = NULL;
00061 static volatile ProcSignalSlot *MyProcSignalSlot = NULL;
00062
00063 static bool CheckProcSignal(ProcSignalReason reason);
00064 static void CleanupProcSignalState(int status, Datum arg);
00065
00066
00067
00068
00069
00070 Size
00071 ProcSignalShmemSize(void)
00072 {
00073 return NumProcSignalSlots * sizeof(ProcSignalSlot);
00074 }
00075
00076
00077
00078
00079
00080 void
00081 ProcSignalShmemInit(void)
00082 {
00083 Size size = ProcSignalShmemSize();
00084 bool found;
00085
00086 ProcSignalSlots = (ProcSignalSlot *)
00087 ShmemInitStruct("ProcSignalSlots", size, &found);
00088
00089
00090 if (!found)
00091 MemSet(ProcSignalSlots, 0, size);
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101 void
00102 ProcSignalInit(int pss_idx)
00103 {
00104 volatile ProcSignalSlot *slot;
00105
00106 Assert(pss_idx >= 1 && pss_idx <= NumProcSignalSlots);
00107
00108 slot = &ProcSignalSlots[pss_idx - 1];
00109
00110
00111 if (slot->pss_pid != 0)
00112 elog(LOG, "process %d taking over ProcSignal slot %d, but it's not empty",
00113 MyProcPid, pss_idx);
00114
00115
00116 MemSet(slot->pss_signalFlags, 0, NUM_PROCSIGNALS * sizeof(sig_atomic_t));
00117
00118
00119 slot->pss_pid = MyProcPid;
00120
00121
00122 MyProcSignalSlot = slot;
00123
00124
00125 on_shmem_exit(CleanupProcSignalState, Int32GetDatum(pss_idx));
00126 }
00127
00128
00129
00130
00131
00132
00133
00134 static void
00135 CleanupProcSignalState(int status, Datum arg)
00136 {
00137 int pss_idx = DatumGetInt32(arg);
00138 volatile ProcSignalSlot *slot;
00139
00140 slot = &ProcSignalSlots[pss_idx - 1];
00141 Assert(slot == MyProcSignalSlot);
00142
00143
00144 if (slot->pss_pid != MyProcPid)
00145 {
00146
00147
00148
00149
00150 elog(LOG, "process %d releasing ProcSignal slot %d, but it contains %d",
00151 MyProcPid, pss_idx, (int) slot->pss_pid);
00152 return;
00153 }
00154
00155 slot->pss_pid = 0;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 int
00170 SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
00171 {
00172 volatile ProcSignalSlot *slot;
00173
00174 if (backendId != InvalidBackendId)
00175 {
00176 slot = &ProcSignalSlots[backendId - 1];
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 if (slot->pss_pid == pid)
00187 {
00188
00189 slot->pss_signalFlags[reason] = true;
00190
00191 return kill(pid, SIGUSR1);
00192 }
00193 }
00194 else
00195 {
00196
00197
00198
00199
00200
00201
00202 int i;
00203
00204 for (i = NumProcSignalSlots - 1; i >= 0; i--)
00205 {
00206 slot = &ProcSignalSlots[i];
00207
00208 if (slot->pss_pid == pid)
00209 {
00210
00211
00212
00213 slot->pss_signalFlags[reason] = true;
00214
00215 return kill(pid, SIGUSR1);
00216 }
00217 }
00218 }
00219
00220 errno = ESRCH;
00221 return -1;
00222 }
00223
00224
00225
00226
00227
00228
00229 static bool
00230 CheckProcSignal(ProcSignalReason reason)
00231 {
00232 volatile ProcSignalSlot *slot = MyProcSignalSlot;
00233
00234 if (slot != NULL)
00235 {
00236
00237 if (slot->pss_signalFlags[reason])
00238 {
00239 slot->pss_signalFlags[reason] = false;
00240 return true;
00241 }
00242 }
00243
00244 return false;
00245 }
00246
00247
00248
00249
00250 void
00251 procsignal_sigusr1_handler(SIGNAL_ARGS)
00252 {
00253 int save_errno = errno;
00254
00255 if (CheckProcSignal(PROCSIG_CATCHUP_INTERRUPT))
00256 HandleCatchupInterrupt();
00257
00258 if (CheckProcSignal(PROCSIG_NOTIFY_INTERRUPT))
00259 HandleNotifyInterrupt();
00260
00261 if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_DATABASE))
00262 RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_DATABASE);
00263
00264 if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_TABLESPACE))
00265 RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_TABLESPACE);
00266
00267 if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_LOCK))
00268 RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_LOCK);
00269
00270 if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_SNAPSHOT))
00271 RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_SNAPSHOT);
00272
00273 if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK))
00274 RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK);
00275
00276 if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN))
00277 RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
00278
00279 latch_sigusr1_handler();
00280
00281 errno = save_errno;
00282 }