Branch data Line data Source code
1 : : /*--------------------------------------------------------------------
2 : : * bgworker.c
3 : : * POSTGRES pluggable background workers implementation
4 : : *
5 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
6 : : *
7 : : * IDENTIFICATION
8 : : * src/backend/postmaster/bgworker.c
9 : : *
10 : : *-------------------------------------------------------------------------
11 : : */
12 : :
13 : : #include "postgres.h"
14 : :
15 : : #include "access/parallel.h"
16 : : #include "libpq/pqsignal.h"
17 : : #include "miscadmin.h"
18 : : #include "pgstat.h"
19 : : #include "port/atomics.h"
20 : : #include "postmaster/bgworker_internals.h"
21 : : #include "postmaster/postmaster.h"
22 : : #include "replication/logicallauncher.h"
23 : : #include "replication/logicalworker.h"
24 : : #include "storage/ipc.h"
25 : : #include "storage/latch.h"
26 : : #include "storage/lwlock.h"
27 : : #include "storage/pmsignal.h"
28 : : #include "storage/proc.h"
29 : : #include "storage/procarray.h"
30 : : #include "storage/procsignal.h"
31 : : #include "storage/shmem.h"
32 : : #include "tcop/tcopprot.h"
33 : : #include "utils/ascii.h"
34 : : #include "utils/memutils.h"
35 : : #include "utils/ps_status.h"
36 : : #include "utils/timeout.h"
37 : :
38 : : /*
39 : : * The postmaster's list of registered background workers, in private memory.
40 : : */
41 : : dlist_head BackgroundWorkerList = DLIST_STATIC_INIT(BackgroundWorkerList);
42 : :
43 : : /*
44 : : * BackgroundWorkerSlots exist in shared memory and can be accessed (via
45 : : * the BackgroundWorkerArray) by both the postmaster and by regular backends.
46 : : * However, the postmaster cannot take locks, even spinlocks, because this
47 : : * might allow it to crash or become wedged if shared memory gets corrupted.
48 : : * Such an outcome is intolerable. Therefore, we need a lockless protocol
49 : : * for coordinating access to this data.
50 : : *
51 : : * The 'in_use' flag is used to hand off responsibility for the slot between
52 : : * the postmaster and the rest of the system. When 'in_use' is false,
53 : : * the postmaster will ignore the slot entirely, except for the 'in_use' flag
54 : : * itself, which it may read. In this state, regular backends may modify the
55 : : * slot. Once a backend sets 'in_use' to true, the slot becomes the
56 : : * responsibility of the postmaster. Regular backends may no longer modify it,
57 : : * but the postmaster may examine it. Thus, a backend initializing a slot
58 : : * must fully initialize the slot - and insert a write memory barrier - before
59 : : * marking it as in use.
60 : : *
61 : : * As an exception, however, even when the slot is in use, regular backends
62 : : * may set the 'terminate' flag for a slot, telling the postmaster not
63 : : * to restart it. Once the background worker is no longer running, the slot
64 : : * will be released for reuse.
65 : : *
66 : : * In addition to coordinating with the postmaster, backends modifying this
67 : : * data structure must coordinate with each other. Since they can take locks,
68 : : * this is straightforward: any backend wishing to manipulate a slot must
69 : : * take BackgroundWorkerLock in exclusive mode. Backends wishing to read
70 : : * data that might get concurrently modified by other backends should take
71 : : * this lock in shared mode. No matter what, backends reading this data
72 : : * structure must be able to tolerate concurrent modifications by the
73 : : * postmaster.
74 : : */
75 : : typedef struct BackgroundWorkerSlot
76 : : {
77 : : bool in_use;
78 : : bool terminate;
79 : : pid_t pid; /* InvalidPid = not started yet; 0 = dead */
80 : : uint64 generation; /* incremented when slot is recycled */
81 : : BackgroundWorker worker;
82 : : } BackgroundWorkerSlot;
83 : :
84 : : /*
85 : : * In order to limit the total number of parallel workers (according to
86 : : * max_parallel_workers GUC), we maintain the number of active parallel
87 : : * workers. Since the postmaster cannot take locks, two variables are used for
88 : : * this purpose: the number of registered parallel workers (modified by the
89 : : * backends, protected by BackgroundWorkerLock) and the number of terminated
90 : : * parallel workers (modified only by the postmaster, lockless). The active
91 : : * number of parallel workers is the number of registered workers minus the
92 : : * terminated ones. These counters can of course overflow, but it's not
93 : : * important here since the subtraction will still give the right number.
94 : : */
95 : : typedef struct BackgroundWorkerArray
96 : : {
97 : : int total_slots;
98 : : uint32 parallel_register_count;
99 : : uint32 parallel_terminate_count;
100 : : BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER];
101 : : } BackgroundWorkerArray;
102 : :
103 : : struct BackgroundWorkerHandle
104 : : {
105 : : int slot;
106 : : uint64 generation;
107 : : };
108 : :
109 : : static BackgroundWorkerArray *BackgroundWorkerData;
110 : :
111 : : /*
112 : : * List of internal background worker entry points. We need this for
113 : : * reasons explained in LookupBackgroundWorkerFunction(), below.
114 : : */
115 : : static const struct
116 : : {
117 : : const char *fn_name;
118 : : bgworker_main_type fn_addr;
119 : : } InternalBGWorkers[] =
120 : :
121 : : {
122 : : {
123 : : "ParallelWorkerMain", ParallelWorkerMain
124 : : },
125 : : {
126 : : "ApplyLauncherMain", ApplyLauncherMain
127 : : },
128 : : {
129 : : "ApplyWorkerMain", ApplyWorkerMain
130 : : },
131 : : {
132 : : "ParallelApplyWorkerMain", ParallelApplyWorkerMain
133 : : },
134 : : {
135 : : "TableSyncWorkerMain", TableSyncWorkerMain
136 : : },
137 : : {
138 : : "SequenceSyncWorkerMain", SequenceSyncWorkerMain
139 : : }
140 : : };
141 : :
142 : : /* Private functions. */
143 : : static bgworker_main_type LookupBackgroundWorkerFunction(const char *libraryname, const char *funcname);
144 : :
145 : :
146 : : /*
147 : : * Calculate shared memory needed.
148 : : */
149 : : Size
150 : 15 : BackgroundWorkerShmemSize(void)
151 : : {
152 : 15 : Size size;
153 : :
154 : : /* Array of workers is variably sized. */
155 : 15 : size = offsetof(BackgroundWorkerArray, slot);
156 : 15 : size = add_size(size, mul_size(max_worker_processes,
157 : : sizeof(BackgroundWorkerSlot)));
158 : :
159 : 30 : return size;
160 : 15 : }
161 : :
162 : : /*
163 : : * Initialize shared memory.
164 : : */
165 : : void
166 : 6 : BackgroundWorkerShmemInit(void)
167 : : {
168 : 6 : bool found;
169 : :
170 : 6 : BackgroundWorkerData = ShmemInitStruct("Background Worker Data",
171 : 6 : BackgroundWorkerShmemSize(),
172 : : &found);
173 [ + - ]: 6 : if (!IsUnderPostmaster)
174 : : {
175 : 6 : dlist_iter iter;
176 : 6 : int slotno = 0;
177 : :
178 : 6 : BackgroundWorkerData->total_slots = max_worker_processes;
179 : 6 : BackgroundWorkerData->parallel_register_count = 0;
180 : 6 : BackgroundWorkerData->parallel_terminate_count = 0;
181 : :
182 : : /*
183 : : * Copy contents of worker list into shared memory. Record the shared
184 : : * memory slot assigned to each worker. This ensures a 1-to-1
185 : : * correspondence between the postmaster's private list and the array
186 : : * in shared memory.
187 : : */
188 [ + - + + ]: 8 : dlist_foreach(iter, &BackgroundWorkerList)
189 : : {
190 : 2 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
191 : 2 : RegisteredBgWorker *rw;
192 : :
193 : 2 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
194 [ + - ]: 2 : Assert(slotno < max_worker_processes);
195 : 2 : slot->in_use = true;
196 : 2 : slot->terminate = false;
197 : 2 : slot->pid = InvalidPid;
198 : 2 : slot->generation = 0;
199 : 2 : rw->rw_shmem_slot = slotno;
200 : 2 : rw->rw_worker.bgw_notify_pid = 0; /* might be reinit after crash */
201 : 2 : memcpy(&slot->worker, &rw->rw_worker, sizeof(BackgroundWorker));
202 : 2 : ++slotno;
203 : 2 : }
204 : :
205 : : /*
206 : : * Mark any remaining slots as not in use.
207 : : */
208 [ + + ]: 52 : while (slotno < max_worker_processes)
209 : : {
210 : 46 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
211 : :
212 : 46 : slot->in_use = false;
213 : 46 : ++slotno;
214 : 46 : }
215 : 6 : }
216 : : else
217 [ # # ]: 0 : Assert(found);
218 : 6 : }
219 : :
220 : : /*
221 : : * Search the postmaster's backend-private list of RegisteredBgWorker objects
222 : : * for the one that maps to the given slot number.
223 : : */
224 : : static RegisteredBgWorker *
225 : 752 : FindRegisteredWorkerBySlotNumber(int slotno)
226 : : {
227 : 752 : dlist_iter iter;
228 : :
229 [ + - + + ]: 1944 : dlist_foreach(iter, &BackgroundWorkerList)
230 : : {
231 : 1466 : RegisteredBgWorker *rw;
232 : :
233 : 1466 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
234 [ + + ]: 1466 : if (rw->rw_shmem_slot == slotno)
235 : 274 : return rw;
236 [ + + ]: 1466 : }
237 : :
238 : 478 : return NULL;
239 : 752 : }
240 : :
241 : : /*
242 : : * Notice changes to shared memory made by other backends.
243 : : * Accept new worker requests only if allow_new_workers is true.
244 : : *
245 : : * This code runs in the postmaster, so we must be very careful not to assume
246 : : * that shared memory contents are sane. Otherwise, a rogue backend could
247 : : * take out the postmaster.
248 : : */
249 : : void
250 : 207 : BackgroundWorkerStateChange(bool allow_new_workers)
251 : : {
252 : 207 : int slotno;
253 : :
254 : : /*
255 : : * The total number of slots stored in shared memory should match our
256 : : * notion of max_worker_processes. If it does not, something is very
257 : : * wrong. Further down, we always refer to this value as
258 : : * max_worker_processes, in case shared memory gets corrupted while we're
259 : : * looping.
260 : : */
261 [ - + ]: 207 : if (max_worker_processes != BackgroundWorkerData->total_slots)
262 : : {
263 [ # # # # ]: 0 : ereport(LOG,
264 : : (errmsg("inconsistent background worker state (\"max_worker_processes\"=%d, total slots=%d)",
265 : : max_worker_processes,
266 : : BackgroundWorkerData->total_slots)));
267 : 0 : return;
268 : : }
269 : :
270 : : /*
271 : : * Iterate through slots, looking for newly-registered workers or workers
272 : : * who must die.
273 : : */
274 [ + + ]: 1863 : for (slotno = 0; slotno < max_worker_processes; ++slotno)
275 : : {
276 : 1656 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
277 : 1656 : RegisteredBgWorker *rw;
278 : :
279 [ + + ]: 1656 : if (!slot->in_use)
280 : 904 : continue;
281 : :
282 : : /*
283 : : * Make sure we don't see the in_use flag before the updated slot
284 : : * contents.
285 : : */
286 : 752 : pg_read_barrier();
287 : :
288 : : /* See whether we already know about this worker. */
289 : 752 : rw = FindRegisteredWorkerBySlotNumber(slotno);
290 [ + + ]: 752 : if (rw != NULL)
291 : : {
292 : : /*
293 : : * In general, the worker data can't change after it's initially
294 : : * registered. However, someone can set the terminate flag.
295 : : */
296 [ + + - + ]: 274 : if (slot->terminate && !rw->rw_terminate)
297 : : {
298 : 2 : rw->rw_terminate = true;
299 [ + - ]: 2 : if (rw->rw_pid != 0)
300 : 2 : kill(rw->rw_pid, SIGTERM);
301 : : else
302 : : {
303 : : /* Report never-started, now-terminated worker as dead. */
304 : 0 : ReportBackgroundWorkerPID(rw);
305 : : }
306 : 2 : }
307 : 274 : continue;
308 : : }
309 : :
310 : : /*
311 : : * If we aren't allowing new workers, then immediately mark it for
312 : : * termination; the next stanza will take care of cleaning it up.
313 : : * Doing this ensures that any process waiting for the worker will get
314 : : * awoken, even though the worker will never be allowed to run.
315 : : */
316 [ + - ]: 478 : if (!allow_new_workers)
317 : 0 : slot->terminate = true;
318 : :
319 : : /*
320 : : * If the worker is marked for termination, we don't need to add it to
321 : : * the registered workers list; we can just free the slot. However, if
322 : : * bgw_notify_pid is set, the process that registered the worker may
323 : : * need to know that we've processed the terminate request, so be sure
324 : : * to signal it.
325 : : */
326 [ - + ]: 478 : if (slot->terminate)
327 : : {
328 : 0 : int notify_pid;
329 : :
330 : : /*
331 : : * We need a memory barrier here to make sure that the load of
332 : : * bgw_notify_pid and the update of parallel_terminate_count
333 : : * complete before the store to in_use.
334 : : */
335 : 0 : notify_pid = slot->worker.bgw_notify_pid;
336 [ # # ]: 0 : if ((slot->worker.bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
337 : 0 : BackgroundWorkerData->parallel_terminate_count++;
338 : 0 : slot->pid = 0;
339 : :
340 : 0 : pg_memory_barrier();
341 : 0 : slot->in_use = false;
342 : :
343 [ # # ]: 0 : if (notify_pid != 0)
344 : 0 : kill(notify_pid, SIGUSR1);
345 : :
346 : : continue;
347 : 0 : }
348 : :
349 : : /*
350 : : * Copy the registration data into the registered workers list.
351 : : */
352 : 478 : rw = MemoryContextAllocExtended(PostmasterContext,
353 : : sizeof(RegisteredBgWorker),
354 : : MCXT_ALLOC_NO_OOM | MCXT_ALLOC_ZERO);
355 [ + - ]: 478 : if (rw == NULL)
356 : : {
357 [ # # # # ]: 0 : ereport(LOG,
358 : : (errcode(ERRCODE_OUT_OF_MEMORY),
359 : : errmsg("out of memory")));
360 : 0 : return;
361 : : }
362 : :
363 : : /*
364 : : * Copy strings in a paranoid way. If shared memory is corrupted, the
365 : : * source data might not even be NUL-terminated.
366 : : */
367 : 956 : ascii_safe_strlcpy(rw->rw_worker.bgw_name,
368 : 478 : slot->worker.bgw_name, BGW_MAXLEN);
369 : 956 : ascii_safe_strlcpy(rw->rw_worker.bgw_type,
370 : 478 : slot->worker.bgw_type, BGW_MAXLEN);
371 : 956 : ascii_safe_strlcpy(rw->rw_worker.bgw_library_name,
372 : 478 : slot->worker.bgw_library_name, MAXPGPATH);
373 : 956 : ascii_safe_strlcpy(rw->rw_worker.bgw_function_name,
374 : 478 : slot->worker.bgw_function_name, BGW_MAXLEN);
375 : :
376 : : /*
377 : : * Copy various fixed-size fields.
378 : : *
379 : : * flags, start_time, and restart_time are examined by the postmaster,
380 : : * but nothing too bad will happen if they are corrupted. The
381 : : * remaining fields will only be examined by the child process. It
382 : : * might crash, but we won't.
383 : : */
384 : 478 : rw->rw_worker.bgw_flags = slot->worker.bgw_flags;
385 : 478 : rw->rw_worker.bgw_start_time = slot->worker.bgw_start_time;
386 : 478 : rw->rw_worker.bgw_restart_time = slot->worker.bgw_restart_time;
387 : 478 : rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg;
388 : 478 : memcpy(rw->rw_worker.bgw_extra, slot->worker.bgw_extra, BGW_EXTRALEN);
389 : :
390 : : /*
391 : : * Copy the PID to be notified about state changes, but only if the
392 : : * postmaster knows about a backend with that PID. It isn't an error
393 : : * if the postmaster doesn't know about the PID, because the backend
394 : : * that requested the worker could have died (or been killed) just
395 : : * after doing so. Nonetheless, at least until we get some experience
396 : : * with how this plays out in the wild, log a message at a relative
397 : : * high debug level.
398 : : */
399 : 478 : rw->rw_worker.bgw_notify_pid = slot->worker.bgw_notify_pid;
400 [ + - ]: 478 : if (!PostmasterMarkPIDForWorkerNotify(rw->rw_worker.bgw_notify_pid))
401 : : {
402 [ # # # # ]: 0 : elog(DEBUG1, "worker notification PID %d is not valid",
403 : : (int) rw->rw_worker.bgw_notify_pid);
404 : 0 : rw->rw_worker.bgw_notify_pid = 0;
405 : 0 : }
406 : :
407 : : /* Initialize postmaster bookkeeping. */
408 : 478 : rw->rw_pid = 0;
409 : 478 : rw->rw_crashed_at = 0;
410 : 478 : rw->rw_shmem_slot = slotno;
411 : 478 : rw->rw_terminate = false;
412 : :
413 : : /* Log it! */
414 [ - + - + ]: 478 : ereport(DEBUG1,
415 : : (errmsg_internal("registering background worker \"%s\"",
416 : : rw->rw_worker.bgw_name)));
417 : :
418 : 478 : dlist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
419 [ + - + ]: 1656 : }
420 [ - + ]: 207 : }
421 : :
422 : : /*
423 : : * Forget about a background worker that's no longer needed.
424 : : *
425 : : * NOTE: The entry is unlinked from BackgroundWorkerList. If the caller is
426 : : * iterating through it, better use a mutable iterator!
427 : : *
428 : : * Caller is responsible for notifying bgw_notify_pid, if appropriate.
429 : : *
430 : : * This function must be invoked only in the postmaster.
431 : : */
432 : : void
433 : 478 : ForgetBackgroundWorker(RegisteredBgWorker *rw)
434 : : {
435 : 478 : BackgroundWorkerSlot *slot;
436 : :
437 [ + - ]: 478 : Assert(rw->rw_shmem_slot < max_worker_processes);
438 : 478 : slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
439 [ + - ]: 478 : Assert(slot->in_use);
440 : :
441 : : /*
442 : : * We need a memory barrier here to make sure that the update of
443 : : * parallel_terminate_count completes before the store to in_use.
444 : : */
445 [ + + ]: 478 : if ((rw->rw_worker.bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
446 : 477 : BackgroundWorkerData->parallel_terminate_count++;
447 : :
448 : 478 : pg_memory_barrier();
449 : 478 : slot->in_use = false;
450 : :
451 [ - + - + ]: 478 : ereport(DEBUG1,
452 : : (errmsg_internal("unregistering background worker \"%s\"",
453 : : rw->rw_worker.bgw_name)));
454 : :
455 : 478 : dlist_delete(&rw->rw_lnode);
456 : 478 : pfree(rw);
457 : 478 : }
458 : :
459 : : /*
460 : : * Report the PID of a newly-launched background worker in shared memory.
461 : : *
462 : : * This function should only be called from the postmaster.
463 : : */
464 : : void
465 : 480 : ReportBackgroundWorkerPID(RegisteredBgWorker *rw)
466 : : {
467 : 480 : BackgroundWorkerSlot *slot;
468 : :
469 [ + - ]: 480 : Assert(rw->rw_shmem_slot < max_worker_processes);
470 : 480 : slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
471 : 480 : slot->pid = rw->rw_pid;
472 : :
473 [ + + ]: 480 : if (rw->rw_worker.bgw_notify_pid != 0)
474 : 478 : kill(rw->rw_worker.bgw_notify_pid, SIGUSR1);
475 : 480 : }
476 : :
477 : : /*
478 : : * Report that the PID of a background worker is now zero because a
479 : : * previously-running background worker has exited.
480 : : *
481 : : * NOTE: The entry may be unlinked from BackgroundWorkerList. If the caller
482 : : * is iterating through it, better use a mutable iterator!
483 : : *
484 : : * This function should only be called from the postmaster.
485 : : */
486 : : void
487 : 479 : ReportBackgroundWorkerExit(RegisteredBgWorker *rw)
488 : : {
489 : 479 : BackgroundWorkerSlot *slot;
490 : 479 : int notify_pid;
491 : :
492 [ + - ]: 479 : Assert(rw->rw_shmem_slot < max_worker_processes);
493 : 479 : slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
494 : 479 : slot->pid = rw->rw_pid;
495 : 479 : notify_pid = rw->rw_worker.bgw_notify_pid;
496 : :
497 : : /*
498 : : * If this worker is slated for deregistration, do that before notifying
499 : : * the process which started it. Otherwise, if that process tries to
500 : : * reuse the slot immediately, it might not be available yet. In theory
501 : : * that could happen anyway if the process checks slot->pid at just the
502 : : * wrong moment, but this makes the window narrower.
503 : : */
504 [ + + + + ]: 479 : if (rw->rw_terminate ||
505 : 2 : rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
506 : 478 : ForgetBackgroundWorker(rw);
507 : :
508 [ + + ]: 479 : if (notify_pid != 0)
509 : 478 : kill(notify_pid, SIGUSR1);
510 : 479 : }
511 : :
512 : : /*
513 : : * Cancel SIGUSR1 notifications for a PID belonging to an exiting backend.
514 : : *
515 : : * This function should only be called from the postmaster.
516 : : */
517 : : void
518 : 22 : BackgroundWorkerStopNotifications(pid_t pid)
519 : : {
520 : 22 : dlist_iter iter;
521 : :
522 [ + - + + ]: 52 : dlist_foreach(iter, &BackgroundWorkerList)
523 : : {
524 : 30 : RegisteredBgWorker *rw;
525 : :
526 : 30 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
527 [ + - ]: 30 : if (rw->rw_worker.bgw_notify_pid == pid)
528 : 0 : rw->rw_worker.bgw_notify_pid = 0;
529 : 30 : }
530 : 22 : }
531 : :
532 : : /*
533 : : * Cancel any not-yet-started worker requests that have waiting processes.
534 : : *
535 : : * This is called during a normal ("smart" or "fast") database shutdown.
536 : : * After this point, no new background workers will be started, so anything
537 : : * that might be waiting for them needs to be kicked off its wait. We do
538 : : * that by canceling the bgworker registration entirely, which is perhaps
539 : : * overkill, but since we're shutting down it does not matter whether the
540 : : * registration record sticks around.
541 : : *
542 : : * This function should only be called from the postmaster.
543 : : */
544 : : void
545 : 1 : ForgetUnstartedBackgroundWorkers(void)
546 : : {
547 : 1 : dlist_mutable_iter iter;
548 : :
549 [ + - + + ]: 2 : dlist_foreach_modify(iter, &BackgroundWorkerList)
550 : : {
551 : 1 : RegisteredBgWorker *rw;
552 : 1 : BackgroundWorkerSlot *slot;
553 : :
554 : 1 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
555 [ + - ]: 1 : Assert(rw->rw_shmem_slot < max_worker_processes);
556 : 1 : slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
557 : :
558 : : /* If it's not yet started, and there's someone waiting ... */
559 [ - + # # ]: 1 : if (slot->pid == InvalidPid &&
560 : 0 : rw->rw_worker.bgw_notify_pid != 0)
561 : : {
562 : : /* ... then zap it, and notify the waiter */
563 : 0 : int notify_pid = rw->rw_worker.bgw_notify_pid;
564 : :
565 : 0 : ForgetBackgroundWorker(rw);
566 [ # # ]: 0 : if (notify_pid != 0)
567 : 0 : kill(notify_pid, SIGUSR1);
568 : 0 : }
569 : 1 : }
570 : 1 : }
571 : :
572 : : /*
573 : : * Reset background worker crash state.
574 : : *
575 : : * We assume that, after a crash-and-restart cycle, background workers without
576 : : * the never-restart flag should be restarted immediately, instead of waiting
577 : : * for bgw_restart_time to elapse. On the other hand, workers with that flag
578 : : * should be forgotten immediately, since we won't ever restart them.
579 : : *
580 : : * This function should only be called from the postmaster.
581 : : */
582 : : void
583 : 0 : ResetBackgroundWorkerCrashTimes(void)
584 : : {
585 : 0 : dlist_mutable_iter iter;
586 : :
587 [ # # # # ]: 0 : dlist_foreach_modify(iter, &BackgroundWorkerList)
588 : : {
589 : 0 : RegisteredBgWorker *rw;
590 : :
591 : 0 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
592 : :
593 [ # # ]: 0 : if (rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
594 : : {
595 : : /*
596 : : * Workers marked BGW_NEVER_RESTART shouldn't get relaunched after
597 : : * the crash, so forget about them. (If we wait until after the
598 : : * crash to forget about them, and they are parallel workers,
599 : : * parallel_terminate_count will get incremented after we've
600 : : * already zeroed parallel_register_count, which would be bad.)
601 : : */
602 : 0 : ForgetBackgroundWorker(rw);
603 : 0 : }
604 : : else
605 : : {
606 : : /*
607 : : * The accounting which we do via parallel_register_count and
608 : : * parallel_terminate_count would get messed up if a worker marked
609 : : * parallel could survive a crash and restart cycle. All such
610 : : * workers should be marked BGW_NEVER_RESTART, and thus control
611 : : * should never reach this branch.
612 : : */
613 [ # # ]: 0 : Assert((rw->rw_worker.bgw_flags & BGWORKER_CLASS_PARALLEL) == 0);
614 : :
615 : : /*
616 : : * Allow this worker to be restarted immediately after we finish
617 : : * resetting.
618 : : */
619 : 0 : rw->rw_crashed_at = 0;
620 : 0 : rw->rw_pid = 0;
621 : :
622 : : /*
623 : : * If there was anyone waiting for it, they're history.
624 : : */
625 : 0 : rw->rw_worker.bgw_notify_pid = 0;
626 : : }
627 : 0 : }
628 : 0 : }
629 : :
630 : : /*
631 : : * Complain about the BackgroundWorker definition using error level elevel.
632 : : * Return true if it looks ok, false if not (unless elevel >= ERROR, in
633 : : * which case we won't return at all in the not-OK case).
634 : : */
635 : : static bool
636 : 1445 : SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
637 : : {
638 : : /* sanity check for flags */
639 : :
640 : : /*
641 : : * We used to support workers not connected to shared memory, but don't
642 : : * anymore. Thus this is a required flag now. We're not removing the flag
643 : : * for compatibility reasons and because the flag still provides some
644 : : * signal when reading code.
645 : : */
646 [ - + ]: 1445 : if (!(worker->bgw_flags & BGWORKER_SHMEM_ACCESS))
647 : : {
648 [ # # # # : 0 : ereport(elevel,
# # # # #
# ]
649 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
650 : : errmsg("background worker \"%s\": background workers without shared memory access are not supported",
651 : : worker->bgw_name)));
652 : 0 : return false;
653 : : }
654 : :
655 [ + + ]: 1445 : if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
656 : : {
657 [ + - ]: 483 : if (worker->bgw_start_time == BgWorkerStart_PostmasterStart)
658 : : {
659 [ # # # # : 0 : ereport(elevel,
# # # # #
# ]
660 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
661 : : errmsg("background worker \"%s\": cannot request database access if starting at postmaster start",
662 : : worker->bgw_name)));
663 : 0 : return false;
664 : : }
665 : :
666 : : /* XXX other checks? */
667 : 483 : }
668 : :
669 : : /* Interruptible workers require a database connection */
670 [ - + # # ]: 1445 : if ((worker->bgw_flags & BGWORKER_INTERRUPTIBLE) &&
671 : 0 : !(worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION))
672 : : {
673 [ # # # # : 0 : ereport(elevel,
# # # # #
# ]
674 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
675 : : errmsg("background worker \"%s\": cannot make background workers interruptible without database access",
676 : : worker->bgw_name)));
677 : 0 : return false;
678 : : }
679 : :
680 [ + + ]: 1445 : if ((worker->bgw_restart_time < 0 &&
681 [ + + ]: 1445 : worker->bgw_restart_time != BGW_NEVER_RESTART) ||
682 : 964 : (worker->bgw_restart_time > USECS_PER_DAY / 1000))
683 : : {
684 [ # # # # : 962 : ereport(elevel,
# # # # #
# ]
685 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
686 : : errmsg("background worker \"%s\": invalid restart interval",
687 : : worker->bgw_name)));
688 : 0 : return false;
689 : : }
690 : :
691 : : /*
692 : : * Parallel workers may not be configured for restart, because the
693 : : * parallel_register_count/parallel_terminate_count accounting can't
694 : : * handle parallel workers lasting through a crash-and-restart cycle.
695 : : */
696 [ + + + - ]: 483 : if (worker->bgw_restart_time != BGW_NEVER_RESTART &&
697 : 2 : (worker->bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
698 : : {
699 [ # # # # : 0 : ereport(elevel,
# # # # #
# ]
700 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
701 : : errmsg("background worker \"%s\": parallel workers may not be configured for restart",
702 : : worker->bgw_name)));
703 : 0 : return false;
704 : : }
705 : :
706 : : /*
707 : : * If bgw_type is not filled in, use bgw_name.
708 : : */
709 [ + - ]: 483 : if (strcmp(worker->bgw_type, "") == 0)
710 : 0 : strcpy(worker->bgw_type, worker->bgw_name);
711 : :
712 : 483 : return true;
713 : 483 : }
714 : :
715 : : /*
716 : : * Standard SIGTERM handler for background workers
717 : : */
718 : : static void
719 : 0 : bgworker_die(SIGNAL_ARGS)
720 : : {
721 : 0 : sigprocmask(SIG_SETMASK, &BlockSig, NULL);
722 : :
723 [ # # # # ]: 0 : ereport(FATAL,
724 : : (errcode(ERRCODE_ADMIN_SHUTDOWN),
725 : : errmsg("terminating background worker \"%s\" due to administrator command",
726 : : MyBgworkerEntry->bgw_type)));
727 : 0 : }
728 : :
729 : : /*
730 : : * Main entry point for background worker processes.
731 : : */
732 : : void
733 : 481 : BackgroundWorkerMain(const void *startup_data, size_t startup_data_len)
734 : : {
735 : 481 : sigjmp_buf local_sigjmp_buf;
736 : 481 : BackgroundWorker *worker;
737 : 481 : bgworker_main_type entrypt;
738 : :
739 [ + - ]: 481 : if (startup_data == NULL)
740 [ # # # # ]: 0 : elog(FATAL, "unable to find bgworker entry");
741 [ + - ]: 481 : Assert(startup_data_len == sizeof(BackgroundWorker));
742 : 481 : worker = MemoryContextAlloc(TopMemoryContext, sizeof(BackgroundWorker));
743 : 481 : memcpy(worker, startup_data, sizeof(BackgroundWorker));
744 : :
745 : : /*
746 : : * Now that we're done reading the startup data, release postmaster's
747 : : * working memory context.
748 : : */
749 [ + + ]: 481 : if (PostmasterContext)
750 : : {
751 : 479 : MemoryContextDelete(PostmasterContext);
752 : 479 : PostmasterContext = NULL;
753 : 479 : }
754 : :
755 : 481 : MyBgworkerEntry = worker;
756 : 481 : MyBackendType = B_BG_WORKER;
757 : 481 : init_ps_display(worker->bgw_name);
758 : :
759 [ + - ]: 481 : Assert(GetProcessingMode() == InitProcessing);
760 : :
761 : : /* Apply PostAuthDelay */
762 [ + - ]: 481 : if (PostAuthDelay > 0)
763 : 0 : pg_usleep(PostAuthDelay * 1000000L);
764 : :
765 : : /*
766 : : * Set up signal handlers.
767 : : */
768 [ + - ]: 481 : if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
769 : : {
770 : : /*
771 : : * SIGINT is used to signal canceling the current action
772 : : */
773 : 481 : pqsignal(SIGINT, StatementCancelHandler);
774 : 481 : pqsignal(SIGUSR1, procsignal_sigusr1_handler);
775 : 481 : pqsignal(SIGFPE, FloatExceptionHandler);
776 : :
777 : : /* XXX Any other handlers needed here? */
778 : 481 : }
779 : : else
780 : : {
781 : 0 : pqsignal(SIGINT, SIG_IGN);
782 : 0 : pqsignal(SIGUSR1, SIG_IGN);
783 : 0 : pqsignal(SIGFPE, SIG_IGN);
784 : : }
785 : 481 : pqsignal(SIGTERM, bgworker_die);
786 : : /* SIGQUIT handler was already set up by InitPostmasterChild */
787 : 481 : pqsignal(SIGHUP, SIG_IGN);
788 : :
789 : 481 : InitializeTimeouts(); /* establishes SIGALRM handler */
790 : :
791 : 481 : pqsignal(SIGPIPE, SIG_IGN);
792 : 481 : pqsignal(SIGUSR2, SIG_IGN);
793 : 481 : pqsignal(SIGCHLD, SIG_DFL);
794 : :
795 : : /*
796 : : * If an exception is encountered, processing resumes here.
797 : : *
798 : : * We just need to clean up, report the error, and go away.
799 : : */
800 [ + + ]: 481 : if (sigsetjmp(local_sigjmp_buf, 1) != 0)
801 : : {
802 : : /* Since not using PG_TRY, must reset error stack by hand */
803 : 2 : error_context_stack = NULL;
804 : :
805 : : /* Prevent interrupts while cleaning up */
806 : 2 : HOLD_INTERRUPTS();
807 : :
808 : : /*
809 : : * sigsetjmp will have blocked all signals, but we may need to accept
810 : : * signals while communicating with our parallel leader. Once we've
811 : : * done HOLD_INTERRUPTS() it should be safe to unblock signals.
812 : : */
813 : 2 : BackgroundWorkerUnblockSignals();
814 : :
815 : : /* Report the error to the parallel leader and the server log */
816 : 2 : EmitErrorReport();
817 : :
818 : : /*
819 : : * Do we need more cleanup here? For shmem-connected bgworkers, we
820 : : * will call InitProcess below, which will install ProcKill as exit
821 : : * callback. That will take care of releasing locks, etc.
822 : : */
823 : :
824 : : /* and go away */
825 : 2 : proc_exit(1);
826 : : }
827 : :
828 : : /* We can now handle ereport(ERROR) */
829 : 479 : PG_exception_stack = &local_sigjmp_buf;
830 : :
831 : : /*
832 : : * Create a per-backend PGPROC struct in shared memory. We must do this
833 : : * before we can use LWLocks or access any shared memory.
834 : : */
835 : 479 : InitProcess();
836 : :
837 : : /*
838 : : * Early initialization.
839 : : */
840 : 479 : BaseInit();
841 : :
842 : : /*
843 : : * Look up the entry point function, loading its library if necessary.
844 : : */
845 : 958 : entrypt = LookupBackgroundWorkerFunction(worker->bgw_library_name,
846 : 479 : worker->bgw_function_name);
847 : :
848 : : /*
849 : : * Note that in normal processes, we would call InitPostgres here. For a
850 : : * worker, however, we don't know what database to connect to, yet; so we
851 : : * need to wait until the user code does it via
852 : : * BackgroundWorkerInitializeConnection().
853 : : */
854 : :
855 : : /*
856 : : * Now invoke the user-defined worker code
857 : : */
858 : 479 : entrypt(worker->bgw_main_arg);
859 : :
860 : : /* ... and if it returns, we're done */
861 : 479 : proc_exit(0);
862 : : }
863 : :
864 : : /*
865 : : * Connect background worker to a database.
866 : : */
867 : : void
868 : 1 : BackgroundWorkerInitializeConnection(const char *dbname, const char *username, uint32 flags)
869 : : {
870 : 1 : BackgroundWorker *worker = MyBgworkerEntry;
871 : 1 : bits32 init_flags = 0; /* never honor session_preload_libraries */
872 : :
873 : : /* ignore datallowconn and ACL_CONNECT? */
874 [ + - ]: 1 : if (flags & BGWORKER_BYPASS_ALLOWCONN)
875 : 0 : init_flags |= INIT_PG_OVERRIDE_ALLOW_CONNS;
876 : : /* ignore rolcanlogin? */
877 [ + - ]: 1 : if (flags & BGWORKER_BYPASS_ROLELOGINCHECK)
878 : 0 : init_flags |= INIT_PG_OVERRIDE_ROLE_LOGIN;
879 : :
880 : : /* XXX is this the right errcode? */
881 [ + - ]: 1 : if (!(worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION))
882 [ # # # # ]: 0 : ereport(FATAL,
883 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
884 : : errmsg("database connection requirement not indicated during registration")));
885 : :
886 : 2 : InitPostgres(dbname, InvalidOid, /* database to connect to */
887 : 1 : username, InvalidOid, /* role to connect as */
888 : 1 : init_flags,
889 : : NULL); /* no out_dbname */
890 : :
891 : : /* it had better not gotten out of "init" mode yet */
892 [ + - ]: 1 : if (!IsInitProcessingMode())
893 [ # # # # ]: 0 : ereport(ERROR,
894 : : (errmsg("invalid processing mode in background worker")));
895 : 1 : SetProcessingMode(NormalProcessing);
896 : 1 : }
897 : :
898 : : /*
899 : : * Connect background worker to a database using OIDs.
900 : : */
901 : : void
902 : 478 : BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags)
903 : : {
904 : 478 : BackgroundWorker *worker = MyBgworkerEntry;
905 : 478 : bits32 init_flags = 0; /* never honor session_preload_libraries */
906 : :
907 : : /* ignore datallowconn and ACL_CONNECT? */
908 [ + + ]: 478 : if (flags & BGWORKER_BYPASS_ALLOWCONN)
909 : 477 : init_flags |= INIT_PG_OVERRIDE_ALLOW_CONNS;
910 : : /* ignore rolcanlogin? */
911 [ + + ]: 478 : if (flags & BGWORKER_BYPASS_ROLELOGINCHECK)
912 : 477 : init_flags |= INIT_PG_OVERRIDE_ROLE_LOGIN;
913 : :
914 : : /* XXX is this the right errcode? */
915 [ + - ]: 478 : if (!(worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION))
916 [ # # # # ]: 0 : ereport(FATAL,
917 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
918 : : errmsg("database connection requirement not indicated during registration")));
919 : :
920 : 956 : InitPostgres(NULL, dboid, /* database to connect to */
921 : 478 : NULL, useroid, /* role to connect as */
922 : 478 : init_flags,
923 : : NULL); /* no out_dbname */
924 : :
925 : : /* it had better not gotten out of "init" mode yet */
926 [ + - ]: 478 : if (!IsInitProcessingMode())
927 [ # # # # ]: 0 : ereport(ERROR,
928 : : (errmsg("invalid processing mode in background worker")));
929 : 478 : SetProcessingMode(NormalProcessing);
930 : 478 : }
931 : :
932 : : /*
933 : : * Block/unblock signals in a background worker
934 : : */
935 : : void
936 : 0 : BackgroundWorkerBlockSignals(void)
937 : : {
938 : 0 : sigprocmask(SIG_SETMASK, &BlockSig, NULL);
939 : 0 : }
940 : :
941 : : void
942 : 481 : BackgroundWorkerUnblockSignals(void)
943 : : {
944 : 481 : sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
945 : 481 : }
946 : :
947 : : /*
948 : : * Register a new static background worker.
949 : : *
950 : : * This can only be called directly from postmaster or in the _PG_init
951 : : * function of a module library that's loaded by shared_preload_libraries;
952 : : * otherwise it will have no effect.
953 : : */
954 : : void
955 : 2 : RegisterBackgroundWorker(BackgroundWorker *worker)
956 : : {
957 : 2 : RegisteredBgWorker *rw;
958 : : static int numworkers = 0;
959 : :
960 : : /*
961 : : * Static background workers can only be registered in the postmaster
962 : : * process.
963 : : */
964 [ + - - + ]: 2 : if (IsUnderPostmaster || !IsPostmasterEnvironment)
965 : : {
966 : : /*
967 : : * In EXEC_BACKEND or single-user mode, we process
968 : : * shared_preload_libraries in backend processes too. We cannot
969 : : * register static background workers at that stage, but many
970 : : * libraries' _PG_init() functions don't distinguish whether they're
971 : : * being loaded in the postmaster or in a backend, they just check
972 : : * process_shared_preload_libraries_in_progress. It's a bit sloppy,
973 : : * but for historical reasons we tolerate it. In EXEC_BACKEND mode,
974 : : * the background workers should already have been registered when the
975 : : * library was loaded in postmaster.
976 : : */
977 [ # # ]: 0 : if (process_shared_preload_libraries_in_progress)
978 : 0 : return;
979 [ # # # # ]: 0 : ereport(LOG,
980 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
981 : : errmsg("background worker \"%s\": must be registered in \"shared_preload_libraries\"",
982 : : worker->bgw_name)));
983 : 0 : return;
984 : : }
985 : :
986 : : /*
987 : : * Cannot register static background workers after calling
988 : : * BackgroundWorkerShmemInit().
989 : : */
990 [ + - ]: 2 : if (BackgroundWorkerData != NULL)
991 [ # # # # ]: 0 : elog(ERROR, "cannot register background worker \"%s\" after shmem init",
992 : : worker->bgw_name);
993 : :
994 [ - + - + ]: 2 : ereport(DEBUG1,
995 : : (errmsg_internal("registering background worker \"%s\"", worker->bgw_name)));
996 : :
997 [ + - ]: 2 : if (!SanityCheckBackgroundWorker(worker, LOG))
998 : 0 : return;
999 : :
1000 [ - + ]: 2 : if (worker->bgw_notify_pid != 0)
1001 : : {
1002 [ # # # # ]: 0 : ereport(LOG,
1003 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1004 : : errmsg("background worker \"%s\": only dynamic background workers can request notification",
1005 : : worker->bgw_name)));
1006 : 0 : return;
1007 : : }
1008 : :
1009 : : /*
1010 : : * Enforce maximum number of workers. Note this is overly restrictive: we
1011 : : * could allow more non-shmem-connected workers, because these don't count
1012 : : * towards the MAX_BACKENDS limit elsewhere. For now, it doesn't seem
1013 : : * important to relax this restriction.
1014 : : */
1015 [ - + ]: 2 : if (++numworkers > max_worker_processes)
1016 : : {
1017 [ # # # # ]: 0 : ereport(LOG,
1018 : : (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
1019 : : errmsg("too many background workers"),
1020 : : errdetail_plural("Up to %d background worker can be registered with the current settings.",
1021 : : "Up to %d background workers can be registered with the current settings.",
1022 : : max_worker_processes,
1023 : : max_worker_processes),
1024 : : errhint("Consider increasing the configuration parameter \"%s\".", "max_worker_processes")));
1025 : 0 : return;
1026 : : }
1027 : :
1028 : : /*
1029 : : * Copy the registration data into the registered workers list.
1030 : : */
1031 : 2 : rw = MemoryContextAllocExtended(PostmasterContext,
1032 : : sizeof(RegisteredBgWorker),
1033 : : MCXT_ALLOC_NO_OOM);
1034 [ + - ]: 2 : if (rw == NULL)
1035 : : {
1036 [ # # # # ]: 0 : ereport(LOG,
1037 : : (errcode(ERRCODE_OUT_OF_MEMORY),
1038 : : errmsg("out of memory")));
1039 : 0 : return;
1040 : : }
1041 : :
1042 : 2 : rw->rw_worker = *worker;
1043 : 2 : rw->rw_pid = 0;
1044 : 2 : rw->rw_crashed_at = 0;
1045 : 2 : rw->rw_terminate = false;
1046 : :
1047 : 2 : dlist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
1048 [ - + ]: 2 : }
1049 : :
1050 : : /*
1051 : : * Register a new background worker from a regular backend.
1052 : : *
1053 : : * Returns true on success and false on failure. Failure typically indicates
1054 : : * that no background worker slots are currently available.
1055 : : *
1056 : : * If handle != NULL, we'll set *handle to a pointer that can subsequently
1057 : : * be used as an argument to GetBackgroundWorkerPid(). The caller can
1058 : : * free this pointer using pfree(), if desired.
1059 : : */
1060 : : bool
1061 : 481 : RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
1062 : : BackgroundWorkerHandle **handle)
1063 : : {
1064 : 481 : int slotno;
1065 : 481 : bool success = false;
1066 : 481 : bool parallel;
1067 : 481 : uint64 generation = 0;
1068 : :
1069 : : /*
1070 : : * We can't register dynamic background workers from the postmaster. If
1071 : : * this is a standalone backend, we're the only process and can't start
1072 : : * any more. In a multi-process environment, it might be theoretically
1073 : : * possible, but we don't currently support it due to locking
1074 : : * considerations; see comments on the BackgroundWorkerSlot data
1075 : : * structure.
1076 : : */
1077 [ - + ]: 481 : if (!IsUnderPostmaster)
1078 : 0 : return false;
1079 : :
1080 [ + - ]: 481 : if (!SanityCheckBackgroundWorker(worker, ERROR))
1081 : 0 : return false;
1082 : :
1083 : 481 : parallel = (worker->bgw_flags & BGWORKER_CLASS_PARALLEL) != 0;
1084 : :
1085 : 481 : LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
1086 : :
1087 : : /*
1088 : : * If this is a parallel worker, check whether there are already too many
1089 : : * parallel workers; if so, don't register another one. Our view of
1090 : : * parallel_terminate_count may be slightly stale, but that doesn't really
1091 : : * matter: we would have gotten the same result if we'd arrived here
1092 : : * slightly earlier anyway. There's no help for it, either, since the
1093 : : * postmaster must not take locks; a memory barrier wouldn't guarantee
1094 : : * anything useful.
1095 : : */
1096 [ + - + + : 481 : if (parallel && (BackgroundWorkerData->parallel_register_count -
+ + + + ]
1097 : 962 : BackgroundWorkerData->parallel_terminate_count) >=
1098 : 481 : max_parallel_workers)
1099 : : {
1100 [ + - ]: 3 : Assert(BackgroundWorkerData->parallel_register_count -
1101 : : BackgroundWorkerData->parallel_terminate_count <=
1102 : : MAX_PARALLEL_WORKER_LIMIT);
1103 : 3 : LWLockRelease(BackgroundWorkerLock);
1104 : 3 : return false;
1105 : : }
1106 : :
1107 : : /*
1108 : : * Look for an unused slot. If we find one, grab it.
1109 : : */
1110 [ + + ]: 1513 : for (slotno = 0; slotno < BackgroundWorkerData->total_slots; ++slotno)
1111 : : {
1112 : 1512 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
1113 : :
1114 [ + + ]: 1512 : if (!slot->in_use)
1115 : : {
1116 : 477 : memcpy(&slot->worker, worker, sizeof(BackgroundWorker));
1117 : 477 : slot->pid = InvalidPid; /* indicates not started yet */
1118 : 477 : slot->generation++;
1119 : 477 : slot->terminate = false;
1120 : 477 : generation = slot->generation;
1121 [ - + ]: 477 : if (parallel)
1122 : 477 : BackgroundWorkerData->parallel_register_count++;
1123 : :
1124 : : /*
1125 : : * Make sure postmaster doesn't see the slot as in use before it
1126 : : * sees the new contents.
1127 : : */
1128 : 477 : pg_write_barrier();
1129 : :
1130 : 477 : slot->in_use = true;
1131 : 477 : success = true;
1132 : 477 : break;
1133 : : }
1134 [ - + + ]: 1512 : }
1135 : :
1136 : 478 : LWLockRelease(BackgroundWorkerLock);
1137 : :
1138 : : /* If we found a slot, tell the postmaster to notice the change. */
1139 [ + + ]: 478 : if (success)
1140 : 477 : SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
1141 : :
1142 : : /*
1143 : : * If we found a slot and the user has provided a handle, initialize it.
1144 : : */
1145 [ + + - + ]: 478 : if (success && handle)
1146 : : {
1147 : 477 : *handle = palloc_object(BackgroundWorkerHandle);
1148 : 477 : (*handle)->slot = slotno;
1149 : 477 : (*handle)->generation = generation;
1150 : 477 : }
1151 : :
1152 : 478 : return success;
1153 : 481 : }
1154 : :
1155 : : /*
1156 : : * Get the PID of a dynamically-registered background worker.
1157 : : *
1158 : : * If the worker is determined to be running, the return value will be
1159 : : * BGWH_STARTED and *pidp will get the PID of the worker process. If the
1160 : : * postmaster has not yet attempted to start the worker, the return value will
1161 : : * be BGWH_NOT_YET_STARTED. Otherwise, the return value is BGWH_STOPPED.
1162 : : *
1163 : : * BGWH_STOPPED can indicate either that the worker is temporarily stopped
1164 : : * (because it is configured for automatic restart and exited non-zero),
1165 : : * or that the worker is permanently stopped (because it exited with exit
1166 : : * code 0, or was not configured for automatic restart), or even that the
1167 : : * worker was unregistered without ever starting (either because startup
1168 : : * failed and the worker is not configured for automatic restart, or because
1169 : : * TerminateBackgroundWorker was used before the worker was successfully
1170 : : * started).
1171 : : */
1172 : : BgwHandleStatus
1173 : 1619043 : GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp)
1174 : : {
1175 : 1619043 : BackgroundWorkerSlot *slot;
1176 : 1619043 : pid_t pid;
1177 : :
1178 [ + - ]: 1619043 : Assert(handle->slot < max_worker_processes);
1179 : 1619043 : slot = &BackgroundWorkerData->slot[handle->slot];
1180 : :
1181 : : /*
1182 : : * We could probably arrange to synchronize access to data using memory
1183 : : * barriers only, but for now, let's just keep it simple and grab the
1184 : : * lock. It seems unlikely that there will be enough traffic here to
1185 : : * result in meaningful contention.
1186 : : */
1187 : 1619043 : LWLockAcquire(BackgroundWorkerLock, LW_SHARED);
1188 : :
1189 : : /*
1190 : : * The generation number can't be concurrently changed while we hold the
1191 : : * lock. The pid, which is updated by the postmaster, can change at any
1192 : : * time, but we assume such changes are atomic. So the value we read
1193 : : * won't be garbage, but it might be out of date by the time the caller
1194 : : * examines it (but that's unavoidable anyway).
1195 : : *
1196 : : * The in_use flag could be in the process of changing from true to false,
1197 : : * but if it is already false then it can't change further.
1198 : : */
1199 [ + + + + ]: 1619043 : if (handle->generation != slot->generation || !slot->in_use)
1200 : 476 : pid = 0;
1201 : : else
1202 : 1618567 : pid = slot->pid;
1203 : :
1204 : : /* All done. */
1205 : 1619043 : LWLockRelease(BackgroundWorkerLock);
1206 : :
1207 [ + + ]: 1619043 : if (pid == 0)
1208 : 477 : return BGWH_STOPPED;
1209 [ + + ]: 1618566 : else if (pid == InvalidPid)
1210 : 106351 : return BGWH_NOT_YET_STARTED;
1211 : 1512215 : *pidp = pid;
1212 : 1512215 : return BGWH_STARTED;
1213 : 1619043 : }
1214 : :
1215 : : /*
1216 : : * Wait for a background worker to start up.
1217 : : *
1218 : : * This is like GetBackgroundWorkerPid(), except that if the worker has not
1219 : : * yet started, we wait for it to do so; thus, BGWH_NOT_YET_STARTED is never
1220 : : * returned. However, if the postmaster has died, we give up and return
1221 : : * BGWH_POSTMASTER_DIED, since it that case we know that startup will not
1222 : : * take place.
1223 : : *
1224 : : * The caller *must* have set our PID as the worker's bgw_notify_pid,
1225 : : * else we will not be awoken promptly when the worker's state changes.
1226 : : */
1227 : : BgwHandleStatus
1228 : 0 : WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
1229 : : {
1230 : 0 : BgwHandleStatus status;
1231 : 0 : int rc;
1232 : :
1233 : 0 : for (;;)
1234 : : {
1235 : 0 : pid_t pid;
1236 : :
1237 [ # # ]: 0 : CHECK_FOR_INTERRUPTS();
1238 : :
1239 : 0 : status = GetBackgroundWorkerPid(handle, &pid);
1240 [ # # ]: 0 : if (status == BGWH_STARTED)
1241 : 0 : *pidp = pid;
1242 [ # # ]: 0 : if (status != BGWH_NOT_YET_STARTED)
1243 : 0 : break;
1244 : :
1245 : 0 : rc = WaitLatch(MyLatch,
1246 : : WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
1247 : : WAIT_EVENT_BGWORKER_STARTUP);
1248 : :
1249 [ # # ]: 0 : if (rc & WL_POSTMASTER_DEATH)
1250 : : {
1251 : 0 : status = BGWH_POSTMASTER_DIED;
1252 : 0 : break;
1253 : : }
1254 : :
1255 : 0 : ResetLatch(MyLatch);
1256 [ # # # ]: 0 : }
1257 : :
1258 : 0 : return status;
1259 : 0 : }
1260 : :
1261 : : /*
1262 : : * Wait for a background worker to stop.
1263 : : *
1264 : : * If the worker hasn't yet started, or is running, we wait for it to stop
1265 : : * and then return BGWH_STOPPED. However, if the postmaster has died, we give
1266 : : * up and return BGWH_POSTMASTER_DIED, because it's the postmaster that
1267 : : * notifies us when a worker's state changes.
1268 : : *
1269 : : * The caller *must* have set our PID as the worker's bgw_notify_pid,
1270 : : * else we will not be awoken promptly when the worker's state changes.
1271 : : */
1272 : : BgwHandleStatus
1273 : 477 : WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *handle)
1274 : : {
1275 : 477 : BgwHandleStatus status;
1276 : 477 : int rc;
1277 : :
1278 : 960 : for (;;)
1279 : : {
1280 : 960 : pid_t pid;
1281 : :
1282 [ + + ]: 960 : CHECK_FOR_INTERRUPTS();
1283 : :
1284 : 960 : status = GetBackgroundWorkerPid(handle, &pid);
1285 [ + + ]: 960 : if (status == BGWH_STOPPED)
1286 : 477 : break;
1287 : :
1288 : 483 : rc = WaitLatch(MyLatch,
1289 : : WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
1290 : : WAIT_EVENT_BGWORKER_SHUTDOWN);
1291 : :
1292 [ - + ]: 483 : if (rc & WL_POSTMASTER_DEATH)
1293 : : {
1294 : 0 : status = BGWH_POSTMASTER_DIED;
1295 : 0 : break;
1296 : : }
1297 : :
1298 : 483 : ResetLatch(MyLatch);
1299 [ - + + ]: 960 : }
1300 : :
1301 : 954 : return status;
1302 : 477 : }
1303 : :
1304 : : /*
1305 : : * Instruct the postmaster to terminate a background worker.
1306 : : *
1307 : : * Note that it's safe to do this without regard to whether the worker is
1308 : : * still running, or even if the worker may already have exited and been
1309 : : * unregistered.
1310 : : */
1311 : : void
1312 : 2 : TerminateBackgroundWorker(BackgroundWorkerHandle *handle)
1313 : : {
1314 : 2 : BackgroundWorkerSlot *slot;
1315 : 2 : bool signal_postmaster = false;
1316 : :
1317 [ + - ]: 2 : Assert(handle->slot < max_worker_processes);
1318 : 2 : slot = &BackgroundWorkerData->slot[handle->slot];
1319 : :
1320 : : /* Set terminate flag in shared memory, unless slot has been reused. */
1321 : 2 : LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
1322 [ - + ]: 2 : if (handle->generation == slot->generation)
1323 : : {
1324 : 2 : slot->terminate = true;
1325 : 2 : signal_postmaster = true;
1326 : 2 : }
1327 : 2 : LWLockRelease(BackgroundWorkerLock);
1328 : :
1329 : : /* Make sure the postmaster notices the change to shared memory. */
1330 [ - + ]: 2 : if (signal_postmaster)
1331 : 2 : SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
1332 : 2 : }
1333 : :
1334 : : /*
1335 : : * Look up (and possibly load) a bgworker entry point function.
1336 : : *
1337 : : * For functions contained in the core code, we use library name "postgres"
1338 : : * and consult the InternalBGWorkers array. External functions are
1339 : : * looked up, and loaded if necessary, using load_external_function().
1340 : : *
1341 : : * The point of this is to pass function names as strings across process
1342 : : * boundaries. We can't pass actual function addresses because of the
1343 : : * possibility that the function has been loaded at a different address
1344 : : * in a different process. This is obviously a hazard for functions in
1345 : : * loadable libraries, but it can happen even for functions in the core code
1346 : : * on platforms using EXEC_BACKEND (e.g., Windows).
1347 : : *
1348 : : * At some point it might be worthwhile to get rid of InternalBGWorkers[]
1349 : : * in favor of applying load_external_function() for core functions too;
1350 : : * but that raises portability issues that are not worth addressing now.
1351 : : */
1352 : : static bgworker_main_type
1353 : 479 : LookupBackgroundWorkerFunction(const char *libraryname, const char *funcname)
1354 : : {
1355 : : /*
1356 : : * If the function is to be loaded from postgres itself, search the
1357 : : * InternalBGWorkers array.
1358 : : */
1359 [ - + ]: 479 : if (strcmp(libraryname, "postgres") == 0)
1360 : : {
1361 : 479 : int i;
1362 : :
1363 [ + - ]: 482 : for (i = 0; i < lengthof(InternalBGWorkers); i++)
1364 : : {
1365 [ + + ]: 482 : if (strcmp(InternalBGWorkers[i].fn_name, funcname) == 0)
1366 : 479 : return InternalBGWorkers[i].fn_addr;
1367 : 3 : }
1368 : :
1369 : : /* We can only reach this by programming error. */
1370 [ # # # # ]: 0 : elog(ERROR, "internal function \"%s\" not found", funcname);
1371 [ - + - ]: 479 : }
1372 : :
1373 : : /* Otherwise load from external library. */
1374 : 0 : return (bgworker_main_type)
1375 : 0 : load_external_function(libraryname, funcname, true, NULL);
1376 : 479 : }
1377 : :
1378 : : /*
1379 : : * Given a PID, get the bgw_type of the background worker. Returns NULL if
1380 : : * not a valid background worker.
1381 : : *
1382 : : * The return value is in static memory belonging to this function, so it has
1383 : : * to be used before calling this function again. This is so that the caller
1384 : : * doesn't have to worry about the background worker locking protocol.
1385 : : */
1386 : : const char *
1387 : 5 : GetBackgroundWorkerTypeByPid(pid_t pid)
1388 : : {
1389 : 5 : int slotno;
1390 : 5 : bool found = false;
1391 : : static char result[BGW_MAXLEN];
1392 : :
1393 : 5 : LWLockAcquire(BackgroundWorkerLock, LW_SHARED);
1394 : :
1395 [ - + ]: 5 : for (slotno = 0; slotno < BackgroundWorkerData->total_slots; slotno++)
1396 : : {
1397 : 5 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
1398 : :
1399 [ + - - + ]: 5 : if (slot->pid > 0 && slot->pid == pid)
1400 : : {
1401 : 5 : strcpy(result, slot->worker.bgw_type);
1402 : 5 : found = true;
1403 : 5 : break;
1404 : : }
1405 [ - + - ]: 5 : }
1406 : :
1407 : 5 : LWLockRelease(BackgroundWorkerLock);
1408 : :
1409 [ + - ]: 5 : if (!found)
1410 : 0 : return NULL;
1411 : :
1412 : 5 : return result;
1413 : 5 : }
1414 : :
1415 : : /*
1416 : : * Terminate all background workers connected to the given database, if the
1417 : : * workers can be interrupted.
1418 : : */
1419 : : void
1420 : 0 : TerminateBackgroundWorkersForDatabase(Oid databaseId)
1421 : : {
1422 : 0 : bool signal_postmaster = false;
1423 : :
1424 : 0 : LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
1425 : :
1426 : : /*
1427 : : * Iterate through slots, looking for workers connected to the given
1428 : : * database.
1429 : : */
1430 [ # # ]: 0 : for (int slotno = 0; slotno < BackgroundWorkerData->total_slots; slotno++)
1431 : : {
1432 : 0 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
1433 : :
1434 [ # # # # ]: 0 : if (slot->in_use &&
1435 : 0 : (slot->worker.bgw_flags & BGWORKER_INTERRUPTIBLE))
1436 : : {
1437 : 0 : PGPROC *proc = BackendPidGetProc(slot->pid);
1438 : :
1439 [ # # # # ]: 0 : if (proc && proc->databaseId == databaseId)
1440 : : {
1441 : 0 : slot->terminate = true;
1442 : 0 : signal_postmaster = true;
1443 : 0 : }
1444 : 0 : }
1445 : 0 : }
1446 : :
1447 : 0 : LWLockRelease(BackgroundWorkerLock);
1448 : :
1449 : : /* Make sure the postmaster notices the change to shared memory. */
1450 [ # # ]: 0 : if (signal_postmaster)
1451 : 0 : SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
1452 : 0 : }
|