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 6522 : BackgroundWorkerShmemSize(void)
151 : {
152 : Size size;
153 :
154 : /* Array of workers is variably sized. */
155 6522 : size = offsetof(BackgroundWorkerArray, slot);
156 6522 : size = add_size(size, mul_size(max_worker_processes,
157 : sizeof(BackgroundWorkerSlot)));
158 :
159 6522 : return size;
160 : }
161 :
162 : /*
163 : * Initialize shared memory.
164 : */
165 : void
166 2276 : BackgroundWorkerShmemInit(void)
167 : {
168 : bool found;
169 :
170 2276 : BackgroundWorkerData = ShmemInitStruct("Background Worker Data",
171 : BackgroundWorkerShmemSize(),
172 : &found);
173 2276 : if (!IsUnderPostmaster)
174 : {
175 : dlist_iter iter;
176 2276 : int slotno = 0;
177 :
178 2276 : BackgroundWorkerData->total_slots = max_worker_processes;
179 2276 : BackgroundWorkerData->parallel_register_count = 0;
180 2276 : 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 4002 : dlist_foreach(iter, &BackgroundWorkerList)
189 : {
190 1726 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
191 : RegisteredBgWorker *rw;
192 :
193 1726 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
194 : Assert(slotno < max_worker_processes);
195 1726 : slot->in_use = true;
196 1726 : slot->terminate = false;
197 1726 : slot->pid = InvalidPid;
198 1726 : slot->generation = 0;
199 1726 : rw->rw_shmem_slot = slotno;
200 1726 : rw->rw_worker.bgw_notify_pid = 0; /* might be reinit after crash */
201 1726 : memcpy(&slot->worker, &rw->rw_worker, sizeof(BackgroundWorker));
202 1726 : ++slotno;
203 : }
204 :
205 : /*
206 : * Mark any remaining slots as not in use.
207 : */
208 18740 : while (slotno < max_worker_processes)
209 : {
210 16464 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
211 :
212 16464 : slot->in_use = false;
213 16464 : ++slotno;
214 : }
215 : }
216 : else
217 : Assert(found);
218 2276 : }
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 9192 : FindRegisteredWorkerBySlotNumber(int slotno)
226 : {
227 : dlist_iter iter;
228 :
229 23012 : dlist_foreach(iter, &BackgroundWorkerList)
230 : {
231 : RegisteredBgWorker *rw;
232 :
233 18964 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
234 18964 : if (rw->rw_shmem_slot == slotno)
235 5144 : return rw;
236 : }
237 :
238 4048 : return NULL;
239 : }
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 2704 : BackgroundWorkerStateChange(bool allow_new_workers)
251 : {
252 : 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 2704 : 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 24624 : for (slotno = 0; slotno < max_worker_processes; ++slotno)
275 : {
276 21920 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
277 : RegisteredBgWorker *rw;
278 :
279 21920 : if (!slot->in_use)
280 12728 : continue;
281 :
282 : /*
283 : * Make sure we don't see the in_use flag before the updated slot
284 : * contents.
285 : */
286 9192 : pg_read_barrier();
287 :
288 : /* See whether we already know about this worker. */
289 9192 : rw = FindRegisteredWorkerBySlotNumber(slotno);
290 9192 : 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 5144 : if (slot->terminate && !rw->rw_terminate)
297 : {
298 20 : rw->rw_terminate = true;
299 20 : if (rw->rw_pid != 0)
300 20 : kill(rw->rw_pid, SIGTERM);
301 : else
302 : {
303 : /* Report never-started, now-terminated worker as dead. */
304 0 : ReportBackgroundWorkerPID(rw);
305 : }
306 : }
307 5144 : 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 4048 : 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 4048 : if (slot->terminate)
327 0 : {
328 : 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 0 : continue;
347 : }
348 :
349 : /*
350 : * Copy the registration data into the registered workers list.
351 : */
352 4048 : rw = MemoryContextAllocExtended(PostmasterContext,
353 : sizeof(RegisteredBgWorker),
354 : MCXT_ALLOC_NO_OOM | MCXT_ALLOC_ZERO);
355 4048 : 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 4048 : ascii_safe_strlcpy(rw->rw_worker.bgw_name,
368 4048 : slot->worker.bgw_name, BGW_MAXLEN);
369 4048 : ascii_safe_strlcpy(rw->rw_worker.bgw_type,
370 4048 : slot->worker.bgw_type, BGW_MAXLEN);
371 4048 : ascii_safe_strlcpy(rw->rw_worker.bgw_library_name,
372 4048 : slot->worker.bgw_library_name, MAXPGPATH);
373 4048 : ascii_safe_strlcpy(rw->rw_worker.bgw_function_name,
374 4048 : 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 4048 : rw->rw_worker.bgw_flags = slot->worker.bgw_flags;
385 4048 : rw->rw_worker.bgw_start_time = slot->worker.bgw_start_time;
386 4048 : rw->rw_worker.bgw_restart_time = slot->worker.bgw_restart_time;
387 4048 : rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg;
388 4048 : 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 4048 : rw->rw_worker.bgw_notify_pid = slot->worker.bgw_notify_pid;
400 4048 : 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 : }
406 :
407 : /* Initialize postmaster bookkeeping. */
408 4048 : rw->rw_pid = 0;
409 4048 : rw->rw_crashed_at = 0;
410 4048 : rw->rw_shmem_slot = slotno;
411 4048 : rw->rw_terminate = false;
412 :
413 : /* Log it! */
414 4048 : ereport(DEBUG1,
415 : (errmsg_internal("registering background worker \"%s\"",
416 : rw->rw_worker.bgw_name)));
417 :
418 4048 : dlist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
419 : }
420 : }
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 3982 : ForgetBackgroundWorker(RegisteredBgWorker *rw)
434 : {
435 : BackgroundWorkerSlot *slot;
436 :
437 : Assert(rw->rw_shmem_slot < max_worker_processes);
438 3982 : slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
439 : 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 3982 : if ((rw->rw_worker.bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
446 2874 : BackgroundWorkerData->parallel_terminate_count++;
447 :
448 3982 : pg_memory_barrier();
449 3982 : slot->in_use = false;
450 :
451 3982 : ereport(DEBUG1,
452 : (errmsg_internal("unregistering background worker \"%s\"",
453 : rw->rw_worker.bgw_name)));
454 :
455 3982 : dlist_delete(&rw->rw_lnode);
456 3982 : pfree(rw);
457 3982 : }
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 5558 : ReportBackgroundWorkerPID(RegisteredBgWorker *rw)
466 : {
467 : BackgroundWorkerSlot *slot;
468 :
469 : Assert(rw->rw_shmem_slot < max_worker_processes);
470 5558 : slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
471 5558 : slot->pid = rw->rw_pid;
472 :
473 5558 : if (rw->rw_worker.bgw_notify_pid != 0)
474 4048 : kill(rw->rw_worker.bgw_notify_pid, SIGUSR1);
475 5558 : }
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 4882 : ReportBackgroundWorkerExit(RegisteredBgWorker *rw)
488 : {
489 : BackgroundWorkerSlot *slot;
490 : int notify_pid;
491 :
492 : Assert(rw->rw_shmem_slot < max_worker_processes);
493 4882 : slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
494 4882 : slot->pid = rw->rw_pid;
495 4882 : 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 4882 : if (rw->rw_terminate ||
505 1376 : rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
506 3982 : ForgetBackgroundWorker(rw);
507 :
508 4882 : if (notify_pid != 0)
509 3932 : kill(notify_pid, SIGUSR1);
510 4882 : }
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 518 : BackgroundWorkerStopNotifications(pid_t pid)
519 : {
520 : dlist_iter iter;
521 :
522 1696 : dlist_foreach(iter, &BackgroundWorkerList)
523 : {
524 : RegisteredBgWorker *rw;
525 :
526 1178 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
527 1178 : if (rw->rw_worker.bgw_notify_pid == pid)
528 54 : rw->rw_worker.bgw_notify_pid = 0;
529 : }
530 518 : }
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 1128 : ForgetUnstartedBackgroundWorkers(void)
546 : {
547 : dlist_mutable_iter iter;
548 :
549 2240 : dlist_foreach_modify(iter, &BackgroundWorkerList)
550 : {
551 : RegisteredBgWorker *rw;
552 : BackgroundWorkerSlot *slot;
553 :
554 1112 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
555 : Assert(rw->rw_shmem_slot < max_worker_processes);
556 1112 : slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
557 :
558 : /* If it's not yet started, and there's someone waiting ... */
559 1112 : if (slot->pid == InvalidPid &&
560 114 : 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 : }
569 : }
570 1128 : }
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 10 : ResetBackgroundWorkerCrashTimes(void)
584 : {
585 : dlist_mutable_iter iter;
586 :
587 20 : dlist_foreach_modify(iter, &BackgroundWorkerList)
588 : {
589 : RegisteredBgWorker *rw;
590 :
591 10 : rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur);
592 :
593 10 : 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 : }
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 : 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 10 : rw->rw_crashed_at = 0;
620 10 : rw->rw_pid = 0;
621 :
622 : /*
623 : * If there was anyone waiting for it, they're history.
624 : */
625 10 : rw->rw_worker.bgw_notify_pid = 0;
626 : }
627 : }
628 10 : }
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 5544 : 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 5544 : 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 5544 : if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
656 : {
657 5526 : 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 : }
668 :
669 : /* Interruptible workers require a database connection */
670 5544 : if ((worker->bgw_flags & BGWORKER_INTERRUPTIBLE) &&
671 8 : !(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 5544 : if ((worker->bgw_restart_time < 0 &&
681 3820 : worker->bgw_restart_time != BGW_NEVER_RESTART) ||
682 5544 : (worker->bgw_restart_time > USECS_PER_DAY / 1000))
683 : {
684 0 : 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 5544 : if (worker->bgw_restart_time != BGW_NEVER_RESTART &&
697 1724 : (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 5544 : if (strcmp(worker->bgw_type, "") == 0)
710 0 : strcpy(worker->bgw_type, worker->bgw_name);
711 :
712 5544 : return true;
713 : }
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 : }
728 :
729 : /*
730 : * Main entry point for background worker processes.
731 : */
732 : void
733 4932 : BackgroundWorkerMain(const void *startup_data, size_t startup_data_len)
734 : {
735 : sigjmp_buf local_sigjmp_buf;
736 : BackgroundWorker *worker;
737 : bgworker_main_type entrypt;
738 :
739 4932 : if (startup_data == NULL)
740 0 : elog(FATAL, "unable to find bgworker entry");
741 : Assert(startup_data_len == sizeof(BackgroundWorker));
742 4932 : worker = MemoryContextAlloc(TopMemoryContext, sizeof(BackgroundWorker));
743 4932 : 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 4932 : if (PostmasterContext)
750 : {
751 4932 : MemoryContextDelete(PostmasterContext);
752 4932 : PostmasterContext = NULL;
753 : }
754 :
755 4932 : MyBgworkerEntry = worker;
756 4932 : MyBackendType = B_BG_WORKER;
757 4932 : init_ps_display(worker->bgw_name);
758 :
759 : Assert(GetProcessingMode() == InitProcessing);
760 :
761 : /* Apply PostAuthDelay */
762 4932 : if (PostAuthDelay > 0)
763 0 : pg_usleep(PostAuthDelay * 1000000L);
764 :
765 : /*
766 : * Set up signal handlers.
767 : */
768 4932 : if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
769 : {
770 : /*
771 : * SIGINT is used to signal canceling the current action
772 : */
773 4914 : pqsignal(SIGINT, StatementCancelHandler);
774 4914 : pqsignal(SIGUSR1, procsignal_sigusr1_handler);
775 4914 : pqsignal(SIGFPE, FloatExceptionHandler);
776 :
777 : /* XXX Any other handlers needed here? */
778 : }
779 : else
780 : {
781 18 : pqsignal(SIGINT, SIG_IGN);
782 18 : pqsignal(SIGUSR1, SIG_IGN);
783 18 : pqsignal(SIGFPE, SIG_IGN);
784 : }
785 4932 : pqsignal(SIGTERM, bgworker_die);
786 : /* SIGQUIT handler was already set up by InitPostmasterChild */
787 4932 : pqsignal(SIGHUP, SIG_IGN);
788 :
789 4932 : InitializeTimeouts(); /* establishes SIGALRM handler */
790 :
791 4932 : pqsignal(SIGPIPE, SIG_IGN);
792 4932 : pqsignal(SIGUSR2, SIG_IGN);
793 4932 : 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 4932 : if (sigsetjmp(local_sigjmp_buf, 1) != 0)
801 : {
802 : /* Since not using PG_TRY, must reset error stack by hand */
803 294 : error_context_stack = NULL;
804 :
805 : /* Prevent interrupts while cleaning up */
806 294 : 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 294 : BackgroundWorkerUnblockSignals();
814 :
815 : /* Report the error to the parallel leader and the server log */
816 294 : 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 294 : proc_exit(1);
826 : }
827 :
828 : /* We can now handle ereport(ERROR) */
829 4932 : 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 4932 : InitProcess();
836 :
837 : /*
838 : * Early initialization.
839 : */
840 4932 : BaseInit();
841 :
842 : /*
843 : * Look up the entry point function, loading its library if necessary.
844 : */
845 9864 : entrypt = LookupBackgroundWorkerFunction(worker->bgw_library_name,
846 4932 : 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 4932 : entrypt(worker->bgw_main_arg);
859 :
860 : /* ... and if it returns, we're done */
861 2868 : proc_exit(0);
862 : }
863 :
864 : /*
865 : * Connect background worker to a database.
866 : */
867 : void
868 906 : BackgroundWorkerInitializeConnection(const char *dbname, const char *username, uint32 flags)
869 : {
870 906 : BackgroundWorker *worker = MyBgworkerEntry;
871 906 : bits32 init_flags = 0; /* never honor session_preload_libraries */
872 :
873 : /* ignore datallowconn and ACL_CONNECT? */
874 906 : if (flags & BGWORKER_BYPASS_ALLOWCONN)
875 0 : init_flags |= INIT_PG_OVERRIDE_ALLOW_CONNS;
876 : /* ignore rolcanlogin? */
877 906 : if (flags & BGWORKER_BYPASS_ROLELOGINCHECK)
878 0 : init_flags |= INIT_PG_OVERRIDE_ROLE_LOGIN;
879 :
880 : /* XXX is this the right errcode? */
881 906 : 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 906 : InitPostgres(dbname, InvalidOid, /* database to connect to */
887 : username, InvalidOid, /* role to connect as */
888 : init_flags,
889 : NULL); /* no out_dbname */
890 :
891 : /* it had better not gotten out of "init" mode yet */
892 906 : if (!IsInitProcessingMode())
893 0 : ereport(ERROR,
894 : (errmsg("invalid processing mode in background worker")));
895 906 : SetProcessingMode(NormalProcessing);
896 906 : }
897 :
898 : /*
899 : * Connect background worker to a database using OIDs.
900 : */
901 : void
902 4008 : BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags)
903 : {
904 4008 : BackgroundWorker *worker = MyBgworkerEntry;
905 4008 : bits32 init_flags = 0; /* never honor session_preload_libraries */
906 :
907 : /* ignore datallowconn and ACL_CONNECT? */
908 4008 : if (flags & BGWORKER_BYPASS_ALLOWCONN)
909 2874 : init_flags |= INIT_PG_OVERRIDE_ALLOW_CONNS;
910 : /* ignore rolcanlogin? */
911 4008 : if (flags & BGWORKER_BYPASS_ROLELOGINCHECK)
912 2874 : init_flags |= INIT_PG_OVERRIDE_ROLE_LOGIN;
913 :
914 : /* XXX is this the right errcode? */
915 4008 : 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 4008 : InitPostgres(NULL, dboid, /* database to connect to */
921 : NULL, useroid, /* role to connect as */
922 : init_flags,
923 : NULL); /* no out_dbname */
924 :
925 : /* it had better not gotten out of "init" mode yet */
926 3998 : if (!IsInitProcessingMode())
927 0 : ereport(ERROR,
928 : (errmsg("invalid processing mode in background worker")));
929 3998 : SetProcessingMode(NormalProcessing);
930 3998 : }
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 5226 : BackgroundWorkerUnblockSignals(void)
943 : {
944 5226 : sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
945 5226 : }
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 1730 : RegisterBackgroundWorker(BackgroundWorker *worker)
956 : {
957 : RegisteredBgWorker *rw;
958 : static int numworkers = 0;
959 :
960 : /*
961 : * Static background workers can only be registered in the postmaster
962 : * process.
963 : */
964 1730 : 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 1730 : if (BackgroundWorkerData != NULL)
991 0 : elog(ERROR, "cannot register background worker \"%s\" after shmem init",
992 : worker->bgw_name);
993 :
994 1730 : ereport(DEBUG1,
995 : (errmsg_internal("registering background worker \"%s\"", worker->bgw_name)));
996 :
997 1730 : if (!SanityCheckBackgroundWorker(worker, LOG))
998 0 : return;
999 :
1000 1730 : 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 1730 : 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 1730 : rw = MemoryContextAllocExtended(PostmasterContext,
1032 : sizeof(RegisteredBgWorker),
1033 : MCXT_ALLOC_NO_OOM);
1034 1730 : 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 1730 : rw->rw_worker = *worker;
1043 1730 : rw->rw_pid = 0;
1044 1730 : rw->rw_crashed_at = 0;
1045 1730 : rw->rw_terminate = false;
1046 :
1047 1730 : dlist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
1048 : }
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 3814 : RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
1062 : BackgroundWorkerHandle **handle)
1063 : {
1064 : int slotno;
1065 3814 : bool success = false;
1066 : bool parallel;
1067 3814 : 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 3814 : if (!IsUnderPostmaster)
1078 0 : return false;
1079 :
1080 3814 : if (!SanityCheckBackgroundWorker(worker, ERROR))
1081 0 : return false;
1082 :
1083 3814 : parallel = (worker->bgw_flags & BGWORKER_CLASS_PARALLEL) != 0;
1084 :
1085 3814 : 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 3814 : if (parallel && (BackgroundWorkerData->parallel_register_count -
1097 2904 : BackgroundWorkerData->parallel_terminate_count) >=
1098 : max_parallel_workers)
1099 : {
1100 : Assert(BackgroundWorkerData->parallel_register_count -
1101 : BackgroundWorkerData->parallel_terminate_count <=
1102 : MAX_PARALLEL_WORKER_LIMIT);
1103 20 : LWLockRelease(BackgroundWorkerLock);
1104 20 : return false;
1105 : }
1106 :
1107 : /*
1108 : * Look for an unused slot. If we find one, grab it.
1109 : */
1110 12146 : for (slotno = 0; slotno < BackgroundWorkerData->total_slots; ++slotno)
1111 : {
1112 12134 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
1113 :
1114 12134 : if (!slot->in_use)
1115 : {
1116 3782 : memcpy(&slot->worker, worker, sizeof(BackgroundWorker));
1117 3782 : slot->pid = InvalidPid; /* indicates not started yet */
1118 3782 : slot->generation++;
1119 3782 : slot->terminate = false;
1120 3782 : generation = slot->generation;
1121 3782 : if (parallel)
1122 2874 : 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 3782 : pg_write_barrier();
1129 :
1130 3782 : slot->in_use = true;
1131 3782 : success = true;
1132 3782 : break;
1133 : }
1134 : }
1135 :
1136 3794 : LWLockRelease(BackgroundWorkerLock);
1137 :
1138 : /* If we found a slot, tell the postmaster to notice the change. */
1139 3794 : if (success)
1140 3782 : SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
1141 :
1142 : /*
1143 : * If we found a slot and the user has provided a handle, initialize it.
1144 : */
1145 3794 : if (success && handle)
1146 : {
1147 3782 : *handle = palloc_object(BackgroundWorkerHandle);
1148 3782 : (*handle)->slot = slotno;
1149 3782 : (*handle)->generation = generation;
1150 : }
1151 :
1152 3794 : return success;
1153 : }
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 21622902 : GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp)
1174 : {
1175 : BackgroundWorkerSlot *slot;
1176 : pid_t pid;
1177 :
1178 : Assert(handle->slot < max_worker_processes);
1179 21622902 : 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 21622902 : 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 21622902 : if (handle->generation != slot->generation || !slot->in_use)
1200 2876 : pid = 0;
1201 : else
1202 21620026 : pid = slot->pid;
1203 :
1204 : /* All done. */
1205 21622902 : LWLockRelease(BackgroundWorkerLock);
1206 :
1207 21622902 : if (pid == 0)
1208 2876 : return BGWH_STOPPED;
1209 21620026 : else if (pid == InvalidPid)
1210 940438 : return BGWH_NOT_YET_STARTED;
1211 20679588 : *pidp = pid;
1212 20679588 : return BGWH_STARTED;
1213 : }
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 24 : WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
1229 : {
1230 : BgwHandleStatus status;
1231 : int rc;
1232 :
1233 : for (;;)
1234 14 : {
1235 : pid_t pid;
1236 :
1237 38 : CHECK_FOR_INTERRUPTS();
1238 :
1239 38 : status = GetBackgroundWorkerPid(handle, &pid);
1240 38 : if (status == BGWH_STARTED)
1241 24 : *pidp = pid;
1242 38 : if (status != BGWH_NOT_YET_STARTED)
1243 24 : break;
1244 :
1245 14 : rc = WaitLatch(MyLatch,
1246 : WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
1247 : WAIT_EVENT_BGWORKER_STARTUP);
1248 :
1249 14 : if (rc & WL_POSTMASTER_DEATH)
1250 : {
1251 0 : status = BGWH_POSTMASTER_DIED;
1252 0 : break;
1253 : }
1254 :
1255 14 : ResetLatch(MyLatch);
1256 : }
1257 :
1258 24 : return status;
1259 : }
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 2876 : WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *handle)
1274 : {
1275 : BgwHandleStatus status;
1276 : int rc;
1277 :
1278 : for (;;)
1279 4092 : {
1280 : pid_t pid;
1281 :
1282 6968 : CHECK_FOR_INTERRUPTS();
1283 :
1284 6968 : status = GetBackgroundWorkerPid(handle, &pid);
1285 6968 : if (status == BGWH_STOPPED)
1286 2876 : break;
1287 :
1288 4092 : rc = WaitLatch(MyLatch,
1289 : WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
1290 : WAIT_EVENT_BGWORKER_SHUTDOWN);
1291 :
1292 4092 : if (rc & WL_POSTMASTER_DEATH)
1293 : {
1294 0 : status = BGWH_POSTMASTER_DIED;
1295 0 : break;
1296 : }
1297 :
1298 4092 : ResetLatch(MyLatch);
1299 : }
1300 :
1301 2876 : return status;
1302 : }
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 12 : TerminateBackgroundWorker(BackgroundWorkerHandle *handle)
1313 : {
1314 : BackgroundWorkerSlot *slot;
1315 12 : bool signal_postmaster = false;
1316 :
1317 : Assert(handle->slot < max_worker_processes);
1318 12 : slot = &BackgroundWorkerData->slot[handle->slot];
1319 :
1320 : /* Set terminate flag in shared memory, unless slot has been reused. */
1321 12 : LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
1322 12 : if (handle->generation == slot->generation)
1323 : {
1324 12 : slot->terminate = true;
1325 12 : signal_postmaster = true;
1326 : }
1327 12 : LWLockRelease(BackgroundWorkerLock);
1328 :
1329 : /* Make sure the postmaster notices the change to shared memory. */
1330 12 : if (signal_postmaster)
1331 12 : SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
1332 12 : }
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 4932 : 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 4932 : if (strcmp(libraryname, "postgres") == 0)
1360 : {
1361 : int i;
1362 :
1363 8916 : for (i = 0; i < lengthof(InternalBGWorkers); i++)
1364 : {
1365 8916 : if (strcmp(InternalBGWorkers[i].fn_name, funcname) == 0)
1366 4896 : return InternalBGWorkers[i].fn_addr;
1367 : }
1368 :
1369 : /* We can only reach this by programming error. */
1370 0 : elog(ERROR, "internal function \"%s\" not found", funcname);
1371 : }
1372 :
1373 : /* Otherwise load from external library. */
1374 36 : return (bgworker_main_type)
1375 36 : load_external_function(libraryname, funcname, true, NULL);
1376 : }
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 2062 : GetBackgroundWorkerTypeByPid(pid_t pid)
1388 : {
1389 : int slotno;
1390 2062 : bool found = false;
1391 : static char result[BGW_MAXLEN];
1392 :
1393 2062 : LWLockAcquire(BackgroundWorkerLock, LW_SHARED);
1394 :
1395 2300 : for (slotno = 0; slotno < BackgroundWorkerData->total_slots; slotno++)
1396 : {
1397 2300 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
1398 :
1399 2300 : if (slot->pid > 0 && slot->pid == pid)
1400 : {
1401 2062 : strcpy(result, slot->worker.bgw_type);
1402 2062 : found = true;
1403 2062 : break;
1404 : }
1405 : }
1406 :
1407 2062 : LWLockRelease(BackgroundWorkerLock);
1408 :
1409 2062 : if (!found)
1410 0 : return NULL;
1411 :
1412 2062 : return result;
1413 : }
1414 :
1415 : /*
1416 : * Terminate all background workers connected to the given database, if the
1417 : * workers can be interrupted.
1418 : */
1419 : void
1420 12 : TerminateBackgroundWorkersForDatabase(Oid databaseId)
1421 : {
1422 12 : bool signal_postmaster = false;
1423 :
1424 12 : LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
1425 :
1426 : /*
1427 : * Iterate through slots, looking for workers connected to the given
1428 : * database.
1429 : */
1430 108 : for (int slotno = 0; slotno < BackgroundWorkerData->total_slots; slotno++)
1431 : {
1432 96 : BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
1433 :
1434 96 : if (slot->in_use &&
1435 24 : (slot->worker.bgw_flags & BGWORKER_INTERRUPTIBLE))
1436 : {
1437 6 : PGPROC *proc = BackendPidGetProc(slot->pid);
1438 :
1439 6 : if (proc && proc->databaseId == databaseId)
1440 : {
1441 6 : slot->terminate = true;
1442 6 : signal_postmaster = true;
1443 : }
1444 : }
1445 : }
1446 :
1447 12 : LWLockRelease(BackgroundWorkerLock);
1448 :
1449 : /* Make sure the postmaster notices the change to shared memory. */
1450 12 : if (signal_postmaster)
1451 6 : SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
1452 12 : }
|