]> granicus.if.org Git - postgresql/blob - src/backend/postmaster/bgworker.c
Message style improvements
[postgresql] / src / backend / postmaster / bgworker.c
1 /*--------------------------------------------------------------------
2  * bgworker.c
3  *              POSTGRES pluggable background workers implementation
4  *
5  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
6  *
7  * IDENTIFICATION
8  *        src/backend/postmaster/bgworker.c
9  *
10  *-------------------------------------------------------------------------
11  */
12
13 #include "postgres.h"
14
15 #include "miscadmin.h"
16 #include "postmaster/bgworker_internals.h"
17 #include "storage/barrier.h"
18 #include "storage/lwlock.h"
19 #include "storage/pmsignal.h"
20 #include "storage/shmem.h"
21 #include "utils/ascii.h"
22
23 /*
24  * The postmaster's list of registered background workers, in private memory.
25  */
26 slist_head BackgroundWorkerList = SLIST_STATIC_INIT(BackgroundWorkerList);
27
28 /*
29  * BackgroundWorkerSlots exist in shared memory and can be accessed (via
30  * the BackgroundWorkerArray) by both the postmaster and by regular backends.
31  * However, the postmaster cannot take locks, even spinlocks, because this
32  * might allow it to crash or become wedged if shared memory gets corrupted.
33  * Such an outcome is intolerable.  Therefore, we need a lockless protocol
34  * for coordinating access to this data.
35  *
36  * The 'in_use' flag is used to hand off responsibility for the slot between
37  * the postmaster and the rest of the system.  When 'in_use' is false,
38  * the postmaster will ignore the slot entirely, except for the 'in_use' flag
39  * itself, which it may read.  In this state, regular backends may modify the
40  * slot.  Once a backend sets 'in_use' to true, the slot becomes the
41  * responsibility of the postmaster.  Regular backends may no longer modify it,
42  * but the postmaster may examine it.  Thus, a backend initializing a slot
43  * must fully initialize the slot - and insert a write memory barrier - before
44  * marking it as in use.
45  *
46  * In addition to coordinating with the postmaster, backends modifying this
47  * data structure must coordinate with each other.  Since they can take locks,
48  * this is straightforward: any backend wishing to manipulate a slot must
49  * take BackgroundWorkerLock in exclusive mode.  Backends wishing to read
50  * data that might get concurrently modified by other backends should take
51  * this lock in shared mode.  No matter what, backends reading this data
52  * structure must be able to tolerate concurrent modifications by the
53  * postmaster.
54  */
55 typedef struct BackgroundWorkerSlot
56 {
57         bool    in_use;
58         BackgroundWorker worker;
59 } BackgroundWorkerSlot;
60
61 typedef struct BackgroundWorkerArray
62 {
63         int             total_slots;
64         BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER];
65 } BackgroundWorkerArray;
66
67 BackgroundWorkerArray *BackgroundWorkerData;
68
69 /*
70  * Calculate shared memory needed.
71  */
72 Size
73 BackgroundWorkerShmemSize(void)
74 {
75         Size            size;
76
77         /* Array of workers is variably sized. */
78         size = offsetof(BackgroundWorkerArray, slot);
79         size = add_size(size, mul_size(max_worker_processes,
80                                                                    sizeof(BackgroundWorkerSlot)));
81
82         return size;
83 }
84
85 /*
86  * Initialize shared memory.
87  */
88 void
89 BackgroundWorkerShmemInit(void)
90 {
91         bool            found;
92
93         BackgroundWorkerData = ShmemInitStruct("Background Worker Data",
94                                                                                    BackgroundWorkerShmemSize(),
95                                                                                    &found);
96         if (!IsUnderPostmaster)
97         {
98                 slist_iter      siter;
99                 int                     slotno = 0;
100
101                 BackgroundWorkerData->total_slots = max_worker_processes;
102
103                 /*
104                  * Copy contents of worker list into shared memory.  Record the
105                  * shared memory slot assigned to each worker.  This ensures
106                  * a 1-to-1 correspondence betwen the postmaster's private list and
107                  * the array in shared memory.
108                  */
109                 slist_foreach(siter, &BackgroundWorkerList)
110                 {
111                         BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
112                         RegisteredBgWorker *rw;
113
114                         rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
115                         Assert(slotno < max_worker_processes);
116                         slot->in_use = true;
117                         rw->rw_shmem_slot = slotno;
118                         memcpy(&slot->worker, &rw->rw_worker, sizeof(BackgroundWorker));
119                         ++slotno;
120                 }
121
122                 /*
123                  * Mark any remaining slots as not in use.
124                  */
125                 while (slotno < max_worker_processes)
126                 {
127                         BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
128
129                         slot->in_use = false;
130                         ++slotno;
131                 }
132         }
133         else
134                 Assert(found);
135 }
136
137 /*
138  * Search the postmaster's backend-private list of RegisteredBgWorker objects
139  * for the one that maps to the given slot number.
140  */
141 static RegisteredBgWorker *
142 FindRegisteredWorkerBySlotNumber(int slotno)
143 {
144         slist_iter      siter;
145
146         slist_foreach(siter, &BackgroundWorkerList)
147         {
148                 RegisteredBgWorker *rw;
149
150                 rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
151                 if (rw->rw_shmem_slot == slotno)
152                         return rw;
153         }
154
155         return NULL;
156 }
157
158 /*
159  * Notice changes to shared memory made by other backends.  This code
160  * runs in the postmaster, so we must be very careful not to assume that
161  * shared memory contents are sane.  Otherwise, a rogue backend could take
162  * out the postmaster.
163  */
164 void
165 BackgroundWorkerStateChange(void)
166 {
167         int             slotno;
168
169         /*
170          * The total number of slots stored in shared memory should match our
171          * notion of max_worker_processes.  If it does not, something is very
172          * wrong.  Further down, we always refer to this value as
173          * max_worker_processes, in case shared memory gets corrupted while
174          * we're looping.
175          */
176         if (max_worker_processes != BackgroundWorkerData->total_slots)
177         {
178                 elog(LOG,
179                          "inconsistent background worker state (max_worker_processes=%d, total_slots=%d",
180                         max_worker_processes,
181                         BackgroundWorkerData->total_slots);
182                 return;
183         }
184
185         /*
186          * Iterate through slots, looking for newly-registered workers or
187          * workers who must die.
188          */
189         for (slotno = 0; slotno < max_worker_processes; ++slotno)
190         {
191                 BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
192                 RegisteredBgWorker *rw;
193
194                 if (!slot->in_use)
195                         continue;
196
197                 /*
198                  * Make sure we don't see the in_use flag before the updated slot
199                  * contents.
200                  */
201                 pg_read_barrier();
202
203                 /*
204                  * See whether we already know about this worker.  If not, we need
205                  * to update our backend-private BackgroundWorkerList to match shared
206                  * memory.
207                  */
208                 rw = FindRegisteredWorkerBySlotNumber(slotno);
209                 if (rw != NULL)
210                         continue;
211
212                 /*
213                  * Copy the registration data into the registered workers list.
214                  */
215                 rw = malloc(sizeof(RegisteredBgWorker));
216                 if (rw == NULL)
217                 {
218                         ereport(LOG,
219                                         (errcode(ERRCODE_OUT_OF_MEMORY),
220                                          errmsg("out of memory")));
221                         return;
222                 }
223
224                 /*
225                  * Copy strings in a paranoid way.  If shared memory is corrupted,
226                  * the source data might not even be NUL-terminated.
227                  */
228                 ascii_safe_strlcpy(rw->rw_worker.bgw_name,
229                                                    slot->worker.bgw_name, BGW_MAXLEN);
230                 ascii_safe_strlcpy(rw->rw_worker.bgw_library_name,
231                                                    slot->worker.bgw_library_name, BGW_MAXLEN);
232                 ascii_safe_strlcpy(rw->rw_worker.bgw_function_name,
233                                                    slot->worker.bgw_function_name, BGW_MAXLEN);
234
235                 /*
236                  * Copy remaining fields.
237                  *
238                  * flags, start_time, and restart_time are examined by the
239                  * postmaster, but nothing too bad will happen if they are
240                  * corrupted.  The remaining fields will only be examined by the
241                  * child process.  It might crash, but we won't.
242                  */
243                 rw->rw_worker.bgw_flags = slot->worker.bgw_flags;
244                 rw->rw_worker.bgw_start_time = slot->worker.bgw_start_time;
245                 rw->rw_worker.bgw_restart_time = slot->worker.bgw_restart_time;
246                 rw->rw_worker.bgw_main = slot->worker.bgw_main;
247                 rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg;
248
249                 /* Initialize postmaster bookkeeping. */
250                 rw->rw_backend = NULL;
251                 rw->rw_pid = 0;
252                 rw->rw_child_slot = 0;
253                 rw->rw_crashed_at = 0;
254                 rw->rw_shmem_slot = slotno;
255
256                 /* Log it! */
257                 ereport(LOG,
258                                 (errmsg("registering background worker \"%s\"",
259                                         rw->rw_worker.bgw_name)));
260
261                 slist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
262         }
263 }
264
265 /*
266  * Forget about a background worker that's no longer needed.
267  *
268  * The worker must be identified by passing an slist_mutable_iter that
269  * points to it.  This convention allows deletion of workers during
270  * searches of the worker list, and saves having to search the list again.
271  *
272  * This function must be invoked only in the postmaster.
273  */
274 void
275 ForgetBackgroundWorker(slist_mutable_iter *cur)
276 {
277         RegisteredBgWorker *rw;
278         BackgroundWorkerSlot *slot;
279
280         rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur);
281
282         Assert(rw->rw_shmem_slot < max_worker_processes);
283         slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
284         slot->in_use = false;
285
286         ereport(LOG,
287                         (errmsg("unregistering background worker \"%s\"",
288                                 rw->rw_worker.bgw_name)));
289
290         slist_delete_current(cur);
291         free(rw);
292 }
293
294 #ifdef EXEC_BACKEND
295 /*
296  * In EXEC_BACKEND mode, workers use this to retrieve their details from
297  * shared memory.
298  */
299 BackgroundWorker *
300 BackgroundWorkerEntry(int slotno)
301 {
302         BackgroundWorkerSlot *slot;
303
304         Assert(slotno < BackgroundWorkerData->total_slots);
305         slot = &BackgroundWorkerData->slot[slotno];
306         Assert(slot->in_use);
307         return &slot->worker;           /* can't become free while we're still here */
308 }
309 #endif
310
311 /*
312  * Complain about the BackgroundWorker definition using error level elevel.
313  * Return true if it looks ok, false if not (unless elevel >= ERROR, in
314  * which case we won't return at all in the not-OK case).
315  */
316 static bool
317 SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
318 {
319         /* sanity check for flags */
320         if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
321         {
322                 if (!(worker->bgw_flags & BGWORKER_SHMEM_ACCESS))
323                 {
324                         ereport(elevel,
325                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
326                                          errmsg("background worker \"%s\": must attach to shared memory in order to request a database connection",
327                                                         worker->bgw_name)));
328                         return false;
329                 }
330
331                 if (worker->bgw_start_time == BgWorkerStart_PostmasterStart)
332                 {
333                         ereport(elevel,
334                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
335                                          errmsg("background worker \"%s\": cannot request database access if starting at postmaster start",
336                                                         worker->bgw_name)));
337                         return false;
338                 }
339
340                 /* XXX other checks? */
341         }
342
343         if ((worker->bgw_restart_time < 0 &&
344                  worker->bgw_restart_time != BGW_NEVER_RESTART) ||
345                 (worker->bgw_restart_time > USECS_PER_DAY / 1000))
346         {
347                 ereport(elevel,
348                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
349                                  errmsg("background worker \"%s\": invalid restart interval",
350                                                 worker->bgw_name)));
351                 return false;
352         }
353
354         return true;
355 }
356
357 /*
358  * Register a new background worker while processing shared_preload_libraries.
359  *
360  * This can only be called in the _PG_init function of a module library
361  * that's loaded by shared_preload_libraries; otherwise it has no effect.
362  */
363 void
364 RegisterBackgroundWorker(BackgroundWorker *worker)
365 {
366         RegisteredBgWorker *rw;
367         static int      numworkers = 0;
368
369         if (!IsUnderPostmaster)
370                 ereport(LOG,
371                         (errmsg("registering background worker \"%s\"", worker->bgw_name)));
372
373         if (!process_shared_preload_libraries_in_progress)
374         {
375                 if (!IsUnderPostmaster)
376                         ereport(LOG,
377                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
378                                          errmsg("background worker \"%s\": must be registered in shared_preload_libraries",
379                                                         worker->bgw_name)));
380                 return;
381         }
382
383         if (!SanityCheckBackgroundWorker(worker, LOG))
384                 return;
385
386         /*
387          * Enforce maximum number of workers.  Note this is overly restrictive: we
388          * could allow more non-shmem-connected workers, because these don't count
389          * towards the MAX_BACKENDS limit elsewhere.  For now, it doesn't seem
390          * important to relax this restriction.
391          */
392         if (++numworkers > max_worker_processes)
393         {
394                 ereport(LOG,
395                                 (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
396                                  errmsg("too many background workers"),
397                                  errdetail_plural("Up to %d background worker can be registered with the current settings.",
398                                                                   "Up to %d background workers can be registered with the current settings.",
399                                                                   max_worker_processes,
400                                                                   max_worker_processes),
401                                  errhint("Consider increasing the configuration parameter \"max_worker_processes\".")));
402                 return;
403         }
404
405         /*
406          * Copy the registration data into the registered workers list.
407          */
408         rw = malloc(sizeof(RegisteredBgWorker));
409         if (rw == NULL)
410         {
411                 ereport(LOG,
412                                 (errcode(ERRCODE_OUT_OF_MEMORY),
413                                  errmsg("out of memory")));
414                 return;
415         }
416
417         rw->rw_worker = *worker;
418         rw->rw_backend = NULL;
419         rw->rw_pid = 0;
420         rw->rw_child_slot = 0;
421         rw->rw_crashed_at = 0;
422
423         slist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
424 }
425
426 /*
427  * Register a new background worker from a regular backend.
428  *
429  * Returns true on success and false on failure.  Failure typically indicates
430  * that no background worker slots are currently available.
431  */
432 bool
433 RegisterDynamicBackgroundWorker(BackgroundWorker *worker)
434 {
435         int             slotno;
436         bool    success = false;
437
438         /*
439          * We can't register dynamic background workers from the postmaster.
440          * If this is a standalone backend, we're the only process and can't
441          * start any more.  In a multi-process environement, it might be
442          * theoretically possible, but we don't currently support it due to
443          * locking considerations; see comments on the BackgroundWorkerSlot
444          * data structure.
445          */
446         if (!IsUnderPostmaster)
447                 return false;
448
449         if (!SanityCheckBackgroundWorker(worker, ERROR))
450                 return false;
451
452         LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
453
454         /*
455          * Look for an unused slot.  If we find one, grab it.
456          */
457         for (slotno = 0; slotno < BackgroundWorkerData->total_slots; ++slotno)
458         {
459                 BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
460
461                 if (!slot->in_use)
462                 {
463                         memcpy(&slot->worker, worker, sizeof(BackgroundWorker));
464
465                         /*
466                          * Make sure postmaster doesn't see the slot as in use before
467                          * it sees the new contents.
468                          */
469                         pg_write_barrier();
470
471                         slot->in_use = true;
472                         success = true;
473                         break;
474                 }
475         }
476
477         LWLockRelease(BackgroundWorkerLock);
478
479         /* If we found a slot, tell the postmaster to notice the change. */
480         if (success)
481                 SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
482
483         return success;
484 }