Coverage Report

Created: 2025-06-15 06:31

/src/postgres/src/backend/utils/init/miscinit.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * miscinit.c
4
 *    miscellaneous initialization support stuff
5
 *
6
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 *
10
 * IDENTIFICATION
11
 *    src/backend/utils/init/miscinit.c
12
 *
13
 *-------------------------------------------------------------------------
14
 */
15
#include "postgres.h"
16
17
#include <sys/param.h>
18
#include <signal.h>
19
#include <time.h>
20
#include <sys/file.h>
21
#include <sys/stat.h>
22
#include <sys/time.h>
23
#include <fcntl.h>
24
#include <unistd.h>
25
#include <grp.h>
26
#include <pwd.h>
27
#include <netinet/in.h>
28
#include <arpa/inet.h>
29
#include <utime.h>
30
31
#include "access/htup_details.h"
32
#include "access/parallel.h"
33
#include "catalog/pg_authid.h"
34
#include "common/file_perm.h"
35
#include "libpq/libpq.h"
36
#include "libpq/pqsignal.h"
37
#include "mb/pg_wchar.h"
38
#include "miscadmin.h"
39
#include "pgstat.h"
40
#include "postmaster/autovacuum.h"
41
#include "postmaster/interrupt.h"
42
#include "postmaster/postmaster.h"
43
#include "replication/slotsync.h"
44
#include "storage/fd.h"
45
#include "storage/ipc.h"
46
#include "storage/latch.h"
47
#include "storage/pg_shmem.h"
48
#include "storage/pmsignal.h"
49
#include "storage/proc.h"
50
#include "storage/procarray.h"
51
#include "utils/builtins.h"
52
#include "utils/guc.h"
53
#include "utils/inval.h"
54
#include "utils/memutils.h"
55
#include "utils/pidfile.h"
56
#include "utils/syscache.h"
57
#include "utils/varlena.h"
58
59
60
0
#define DIRECTORY_LOCK_FILE   "postmaster.pid"
61
62
ProcessingMode Mode = InitProcessing;
63
64
BackendType MyBackendType;
65
66
/* List of lock files to be removed at proc exit */
67
static List *lock_files = NIL;
68
69
static Latch LocalLatchData;
70
71
/* ----------------------------------------------------------------
72
 *    ignoring system indexes support stuff
73
 *
74
 * NOTE: "ignoring system indexes" means we do not use the system indexes
75
 * for lookups (either in hardwired catalog accesses or in planner-generated
76
 * plans).  We do, however, still update the indexes when a catalog
77
 * modification is made.
78
 * ----------------------------------------------------------------
79
 */
80
81
bool    IgnoreSystemIndexes = false;
82
83
84
/* ----------------------------------------------------------------
85
 *  common process startup code
86
 * ----------------------------------------------------------------
87
 */
88
89
/*
90
 * Initialize the basic environment for a postmaster child
91
 *
92
 * Should be called as early as possible after the child's startup. However,
93
 * on EXEC_BACKEND builds it does need to be after read_backend_variables().
94
 */
95
void
96
InitPostmasterChild(void)
97
0
{
98
0
  IsUnderPostmaster = true; /* we are a postmaster subprocess now */
99
100
  /*
101
   * Start our win32 signal implementation. This has to be done after we
102
   * read the backend variables, because we need to pick up the signal pipe
103
   * from the parent process.
104
   */
105
#ifdef WIN32
106
  pgwin32_signal_initialize();
107
#endif
108
109
0
  InitProcessGlobals();
110
111
  /*
112
   * make sure stderr is in binary mode before anything can possibly be
113
   * written to it, in case it's actually the syslogger pipe, so the pipe
114
   * chunking protocol isn't disturbed. Non-logpipe data gets translated on
115
   * redirection (e.g. via pg_ctl -l) anyway.
116
   */
117
#ifdef WIN32
118
  _setmode(fileno(stderr), _O_BINARY);
119
#endif
120
121
  /* We don't want the postmaster's proc_exit() handlers */
122
0
  on_exit_reset();
123
124
  /* In EXEC_BACKEND case we will not have inherited BlockSig etc values */
125
#ifdef EXEC_BACKEND
126
  pqinitmask();
127
#endif
128
129
  /* Initialize process-local latch support */
130
0
  InitializeWaitEventSupport();
131
0
  InitProcessLocalLatch();
132
0
  InitializeLatchWaitSet();
133
134
  /*
135
   * If possible, make this process a group leader, so that the postmaster
136
   * can signal any child processes too. Not all processes will have
137
   * children, but for consistency we make all postmaster child processes do
138
   * this.
139
   */
140
0
#ifdef HAVE_SETSID
141
0
  if (setsid() < 0)
142
0
    elog(FATAL, "setsid() failed: %m");
143
0
#endif
144
145
  /*
146
   * Every postmaster child process is expected to respond promptly to
147
   * SIGQUIT at all times.  Therefore we centrally remove SIGQUIT from
148
   * BlockSig and install a suitable signal handler.  (Client-facing
149
   * processes may choose to replace this default choice of handler with
150
   * quickdie().)  All other blockable signals remain blocked for now.
151
   */
152
0
  pqsignal(SIGQUIT, SignalHandlerForCrashExit);
153
154
0
  sigdelset(&BlockSig, SIGQUIT);
155
0
  sigprocmask(SIG_SETMASK, &BlockSig, NULL);
156
157
  /* Request a signal if the postmaster dies, if possible. */
158
0
  PostmasterDeathSignalInit();
159
160
  /* Don't give the pipe to subprograms that we execute. */
161
0
#ifndef WIN32
162
0
  if (fcntl(postmaster_alive_fds[POSTMASTER_FD_WATCH], F_SETFD, FD_CLOEXEC) < 0)
163
0
    ereport(FATAL,
164
0
        (errcode_for_socket_access(),
165
0
         errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
166
0
#endif
167
0
}
168
169
/*
170
 * Initialize the basic environment for a standalone process.
171
 *
172
 * argv0 has to be suitable to find the program's executable.
173
 */
174
void
175
InitStandaloneProcess(const char *argv0)
176
0
{
177
0
  Assert(!IsPostmasterEnvironment);
178
179
0
  MyBackendType = B_STANDALONE_BACKEND;
180
181
  /*
182
   * Start our win32 signal implementation
183
   */
184
#ifdef WIN32
185
  pgwin32_signal_initialize();
186
#endif
187
188
0
  InitProcessGlobals();
189
190
  /* Initialize process-local latch support */
191
0
  InitializeWaitEventSupport();
192
0
  InitProcessLocalLatch();
193
0
  InitializeLatchWaitSet();
194
195
  /*
196
   * For consistency with InitPostmasterChild, initialize signal mask here.
197
   * But we don't unblock SIGQUIT or provide a default handler for it.
198
   */
199
0
  pqinitmask();
200
0
  sigprocmask(SIG_SETMASK, &BlockSig, NULL);
201
202
  /* Compute paths, no postmaster to inherit from */
203
0
  if (my_exec_path[0] == '\0')
204
0
  {
205
0
    if (find_my_exec(argv0, my_exec_path) < 0)
206
0
      elog(FATAL, "%s: could not locate my own executable path",
207
0
         argv0);
208
0
  }
209
210
0
  if (pkglib_path[0] == '\0')
211
0
    get_pkglib_path(my_exec_path, pkglib_path);
212
0
}
213
214
void
215
SwitchToSharedLatch(void)
216
0
{
217
0
  Assert(MyLatch == &LocalLatchData);
218
0
  Assert(MyProc != NULL);
219
220
0
  MyLatch = &MyProc->procLatch;
221
222
0
  if (FeBeWaitSet)
223
0
    ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetLatchPos, WL_LATCH_SET,
224
0
            MyLatch);
225
226
  /*
227
   * Set the shared latch as the local one might have been set. This
228
   * shouldn't normally be necessary as code is supposed to check the
229
   * condition before waiting for the latch, but a bit care can't hurt.
230
   */
231
0
  SetLatch(MyLatch);
232
0
}
233
234
void
235
InitProcessLocalLatch(void)
236
0
{
237
0
  MyLatch = &LocalLatchData;
238
0
  InitLatch(MyLatch);
239
0
}
240
241
void
242
SwitchBackToLocalLatch(void)
243
0
{
244
0
  Assert(MyLatch != &LocalLatchData);
245
0
  Assert(MyProc != NULL && MyLatch == &MyProc->procLatch);
246
247
0
  MyLatch = &LocalLatchData;
248
249
0
  if (FeBeWaitSet)
250
0
    ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetLatchPos, WL_LATCH_SET,
251
0
            MyLatch);
252
253
0
  SetLatch(MyLatch);
254
0
}
255
256
/*
257
 * Return a human-readable string representation of a BackendType.
258
 *
259
 * The string is not localized here, but we mark the strings for translation
260
 * so that callers can invoke _() on the result.
261
 */
262
const char *
263
GetBackendTypeDesc(BackendType backendType)
264
0
{
265
0
  const char *backendDesc = gettext_noop("unknown process type");
266
267
0
  switch (backendType)
268
0
  {
269
0
    case B_INVALID:
270
0
      backendDesc = gettext_noop("not initialized");
271
0
      break;
272
0
    case B_ARCHIVER:
273
0
      backendDesc = gettext_noop("archiver");
274
0
      break;
275
0
    case B_AUTOVAC_LAUNCHER:
276
0
      backendDesc = gettext_noop("autovacuum launcher");
277
0
      break;
278
0
    case B_AUTOVAC_WORKER:
279
0
      backendDesc = gettext_noop("autovacuum worker");
280
0
      break;
281
0
    case B_BACKEND:
282
0
      backendDesc = gettext_noop("client backend");
283
0
      break;
284
0
    case B_DEAD_END_BACKEND:
285
0
      backendDesc = gettext_noop("dead-end client backend");
286
0
      break;
287
0
    case B_BG_WORKER:
288
0
      backendDesc = gettext_noop("background worker");
289
0
      break;
290
0
    case B_BG_WRITER:
291
0
      backendDesc = gettext_noop("background writer");
292
0
      break;
293
0
    case B_CHECKPOINTER:
294
0
      backendDesc = gettext_noop("checkpointer");
295
0
      break;
296
0
    case B_IO_WORKER:
297
0
      backendDesc = gettext_noop("io worker");
298
0
      break;
299
0
    case B_LOGGER:
300
0
      backendDesc = gettext_noop("logger");
301
0
      break;
302
0
    case B_SLOTSYNC_WORKER:
303
0
      backendDesc = gettext_noop("slotsync worker");
304
0
      break;
305
0
    case B_STANDALONE_BACKEND:
306
0
      backendDesc = gettext_noop("standalone backend");
307
0
      break;
308
0
    case B_STARTUP:
309
0
      backendDesc = gettext_noop("startup");
310
0
      break;
311
0
    case B_WAL_RECEIVER:
312
0
      backendDesc = gettext_noop("walreceiver");
313
0
      break;
314
0
    case B_WAL_SENDER:
315
0
      backendDesc = gettext_noop("walsender");
316
0
      break;
317
0
    case B_WAL_SUMMARIZER:
318
0
      backendDesc = gettext_noop("walsummarizer");
319
0
      break;
320
0
    case B_WAL_WRITER:
321
0
      backendDesc = gettext_noop("walwriter");
322
0
      break;
323
0
  }
324
325
0
  return backendDesc;
326
0
}
327
328
/* ----------------------------------------------------------------
329
 *        database path / name support stuff
330
 * ----------------------------------------------------------------
331
 */
332
333
void
334
SetDatabasePath(const char *path)
335
0
{
336
  /* This should happen only once per process */
337
0
  Assert(!DatabasePath);
338
0
  DatabasePath = MemoryContextStrdup(TopMemoryContext, path);
339
0
}
340
341
/*
342
 * Validate the proposed data directory.
343
 *
344
 * Also initialize file and directory create modes and mode mask.
345
 */
346
void
347
checkDataDir(void)
348
0
{
349
0
  struct stat stat_buf;
350
351
0
  Assert(DataDir);
352
353
0
  if (stat(DataDir, &stat_buf) != 0)
354
0
  {
355
0
    if (errno == ENOENT)
356
0
      ereport(FATAL,
357
0
          (errcode_for_file_access(),
358
0
           errmsg("data directory \"%s\" does not exist",
359
0
              DataDir)));
360
0
    else
361
0
      ereport(FATAL,
362
0
          (errcode_for_file_access(),
363
0
           errmsg("could not read permissions of directory \"%s\": %m",
364
0
              DataDir)));
365
0
  }
366
367
  /* eventual chdir would fail anyway, but let's test ... */
368
0
  if (!S_ISDIR(stat_buf.st_mode))
369
0
    ereport(FATAL,
370
0
        (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
371
0
         errmsg("specified data directory \"%s\" is not a directory",
372
0
            DataDir)));
373
374
  /*
375
   * Check that the directory belongs to my userid; if not, reject.
376
   *
377
   * This check is an essential part of the interlock that prevents two
378
   * postmasters from starting in the same directory (see CreateLockFile()).
379
   * Do not remove or weaken it.
380
   *
381
   * XXX can we safely enable this check on Windows?
382
   */
383
0
#if !defined(WIN32) && !defined(__CYGWIN__)
384
0
  if (stat_buf.st_uid != geteuid())
385
0
    ereport(FATAL,
386
0
        (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
387
0
         errmsg("data directory \"%s\" has wrong ownership",
388
0
            DataDir),
389
0
         errhint("The server must be started by the user that owns the data directory.")));
390
0
#endif
391
392
  /*
393
   * Check if the directory has correct permissions.  If not, reject.
394
   *
395
   * Only two possible modes are allowed, 0700 and 0750.  The latter mode
396
   * indicates that group read/execute should be allowed on all newly
397
   * created files and directories.
398
   *
399
   * XXX temporarily suppress check when on Windows, because there may not
400
   * be proper support for Unix-y file permissions.  Need to think of a
401
   * reasonable check to apply on Windows.
402
   */
403
0
#if !defined(WIN32) && !defined(__CYGWIN__)
404
0
  if (stat_buf.st_mode & PG_MODE_MASK_GROUP)
405
0
    ereport(FATAL,
406
0
        (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
407
0
         errmsg("data directory \"%s\" has invalid permissions",
408
0
            DataDir),
409
0
         errdetail("Permissions should be u=rwx (0700) or u=rwx,g=rx (0750).")));
410
0
#endif
411
412
  /*
413
   * Reset creation modes and mask based on the mode of the data directory.
414
   *
415
   * The mask was set earlier in startup to disallow group permissions on
416
   * newly created files and directories.  However, if group read/execute
417
   * are present on the data directory then modify the create modes and mask
418
   * to allow group read/execute on newly created files and directories and
419
   * set the data_directory_mode GUC.
420
   *
421
   * Suppress when on Windows, because there may not be proper support for
422
   * Unix-y file permissions.
423
   */
424
0
#if !defined(WIN32) && !defined(__CYGWIN__)
425
0
  SetDataDirectoryCreatePerm(stat_buf.st_mode);
426
427
0
  umask(pg_mode_mask);
428
0
  data_directory_mode = pg_dir_create_mode;
429
0
#endif
430
431
  /* Check for PG_VERSION */
432
0
  ValidatePgVersion(DataDir);
433
0
}
434
435
/*
436
 * Set data directory, but make sure it's an absolute path.  Use this,
437
 * never set DataDir directly.
438
 */
439
void
440
SetDataDir(const char *dir)
441
0
{
442
0
  char     *new;
443
444
0
  Assert(dir);
445
446
  /* If presented path is relative, convert to absolute */
447
0
  new = make_absolute_path(dir);
448
449
0
  free(DataDir);
450
0
  DataDir = new;
451
0
}
452
453
/*
454
 * Change working directory to DataDir.  Most of the postmaster and backend
455
 * code assumes that we are in DataDir so it can use relative paths to access
456
 * stuff in and under the data directory.  For convenience during path
457
 * setup, however, we don't force the chdir to occur during SetDataDir.
458
 */
459
void
460
ChangeToDataDir(void)
461
0
{
462
0
  Assert(DataDir);
463
464
0
  if (chdir(DataDir) < 0)
465
0
    ereport(FATAL,
466
0
        (errcode_for_file_access(),
467
0
         errmsg("could not change directory to \"%s\": %m",
468
0
            DataDir)));
469
0
}
470
471
472
/* ----------------------------------------------------------------
473
 *  User ID state
474
 *
475
 * We have to track several different values associated with the concept
476
 * of "user ID".
477
 *
478
 * AuthenticatedUserId is determined at connection start and never changes.
479
 *
480
 * SessionUserId is initially the same as AuthenticatedUserId, but can be
481
 * changed by SET SESSION AUTHORIZATION (if AuthenticatedUserId is a
482
 * superuser).  This is the ID reported by the SESSION_USER SQL function.
483
 *
484
 * OuterUserId is the current user ID in effect at the "outer level" (outside
485
 * any transaction or function).  This is initially the same as SessionUserId,
486
 * but can be changed by SET ROLE to any role that SessionUserId is a
487
 * member of.  (XXX rename to something like CurrentRoleId?)
488
 *
489
 * CurrentUserId is the current effective user ID; this is the one to use
490
 * for all normal permissions-checking purposes.  At outer level this will
491
 * be the same as OuterUserId, but it changes during calls to SECURITY
492
 * DEFINER functions, as well as locally in some specialized commands.
493
 *
494
 * SecurityRestrictionContext holds flags indicating reason(s) for changing
495
 * CurrentUserId.  In some cases we need to lock down operations that are
496
 * not directly controlled by privilege settings, and this provides a
497
 * convenient way to do it.
498
 * ----------------------------------------------------------------
499
 */
500
static Oid  AuthenticatedUserId = InvalidOid;
501
static Oid  SessionUserId = InvalidOid;
502
static Oid  OuterUserId = InvalidOid;
503
static Oid  CurrentUserId = InvalidOid;
504
static const char *SystemUser = NULL;
505
506
/* We also have to remember the superuser state of the session user */
507
static bool SessionUserIsSuperuser = false;
508
509
static int  SecurityRestrictionContext = 0;
510
511
/* We also remember if a SET ROLE is currently active */
512
static bool SetRoleIsActive = false;
513
514
/*
515
 * GetUserId - get the current effective user ID.
516
 *
517
 * Note: there's no SetUserId() anymore; use SetUserIdAndSecContext().
518
 */
519
Oid
520
GetUserId(void)
521
0
{
522
0
  Assert(OidIsValid(CurrentUserId));
523
0
  return CurrentUserId;
524
0
}
525
526
527
/*
528
 * GetOuterUserId/SetOuterUserId - get/set the outer-level user ID.
529
 */
530
Oid
531
GetOuterUserId(void)
532
0
{
533
0
  Assert(OidIsValid(OuterUserId));
534
0
  return OuterUserId;
535
0
}
536
537
538
static void
539
SetOuterUserId(Oid userid, bool is_superuser)
540
0
{
541
0
  Assert(SecurityRestrictionContext == 0);
542
0
  Assert(OidIsValid(userid));
543
0
  OuterUserId = userid;
544
545
  /* We force the effective user ID to match, too */
546
0
  CurrentUserId = userid;
547
548
  /* Also update the is_superuser GUC to match OuterUserId's property */
549
0
  SetConfigOption("is_superuser",
550
0
          is_superuser ? "on" : "off",
551
0
          PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
552
0
}
553
554
555
/*
556
 * GetSessionUserId/SetSessionUserId - get/set the session user ID.
557
 */
558
Oid
559
GetSessionUserId(void)
560
0
{
561
0
  Assert(OidIsValid(SessionUserId));
562
0
  return SessionUserId;
563
0
}
564
565
bool
566
GetSessionUserIsSuperuser(void)
567
0
{
568
0
  Assert(OidIsValid(SessionUserId));
569
0
  return SessionUserIsSuperuser;
570
0
}
571
572
static void
573
SetSessionUserId(Oid userid, bool is_superuser)
574
0
{
575
0
  Assert(SecurityRestrictionContext == 0);
576
0
  Assert(OidIsValid(userid));
577
0
  SessionUserId = userid;
578
0
  SessionUserIsSuperuser = is_superuser;
579
0
}
580
581
/*
582
 * Return the system user representing the authenticated identity.
583
 * It is defined in InitializeSystemUser() as auth_method:authn_id.
584
 */
585
const char *
586
GetSystemUser(void)
587
0
{
588
0
  return SystemUser;
589
0
}
590
591
/*
592
 * GetAuthenticatedUserId/SetAuthenticatedUserId - get/set the authenticated
593
 * user ID
594
 */
595
Oid
596
GetAuthenticatedUserId(void)
597
0
{
598
0
  Assert(OidIsValid(AuthenticatedUserId));
599
0
  return AuthenticatedUserId;
600
0
}
601
602
void
603
SetAuthenticatedUserId(Oid userid)
604
0
{
605
0
  Assert(OidIsValid(userid));
606
607
  /* call only once */
608
0
  Assert(!OidIsValid(AuthenticatedUserId));
609
610
0
  AuthenticatedUserId = userid;
611
612
  /* Also mark our PGPROC entry with the authenticated user id */
613
  /* (We assume this is an atomic store so no lock is needed) */
614
0
  MyProc->roleId = userid;
615
0
}
616
617
618
/*
619
 * GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID
620
 * and the SecurityRestrictionContext flags.
621
 *
622
 * Currently there are three valid bits in SecurityRestrictionContext:
623
 *
624
 * SECURITY_LOCAL_USERID_CHANGE indicates that we are inside an operation
625
 * that is temporarily changing CurrentUserId via these functions.  This is
626
 * needed to indicate that the actual value of CurrentUserId is not in sync
627
 * with guc.c's internal state, so SET ROLE has to be disallowed.
628
 *
629
 * SECURITY_RESTRICTED_OPERATION indicates that we are inside an operation
630
 * that does not wish to trust called user-defined functions at all.  The
631
 * policy is to use this before operations, e.g. autovacuum and REINDEX, that
632
 * enumerate relations of a database or schema and run functions associated
633
 * with each found relation.  The relation owner is the new user ID.  Set this
634
 * as soon as possible after locking the relation.  Restore the old user ID as
635
 * late as possible before closing the relation; restoring it shortly after
636
 * close is also tolerable.  If a command has both relation-enumerating and
637
 * non-enumerating modes, e.g. ANALYZE, both modes set this bit.  This bit
638
 * prevents not only SET ROLE, but various other changes of session state that
639
 * normally is unprotected but might possibly be used to subvert the calling
640
 * session later.  An example is replacing an existing prepared statement with
641
 * new code, which will then be executed with the outer session's permissions
642
 * when the prepared statement is next used.  These restrictions are fairly
643
 * draconian, but the functions called in relation-enumerating operations are
644
 * really supposed to be side-effect-free anyway.
645
 *
646
 * SECURITY_NOFORCE_RLS indicates that we are inside an operation which should
647
 * ignore the FORCE ROW LEVEL SECURITY per-table indication.  This is used to
648
 * ensure that FORCE RLS does not mistakenly break referential integrity
649
 * checks.  Note that this is intentionally only checked when running as the
650
 * owner of the table (which should always be the case for referential
651
 * integrity checks).
652
 *
653
 * Unlike GetUserId, GetUserIdAndSecContext does *not* Assert that the current
654
 * value of CurrentUserId is valid; nor does SetUserIdAndSecContext require
655
 * the new value to be valid.  In fact, these routines had better not
656
 * ever throw any kind of error.  This is because they are used by
657
 * StartTransaction and AbortTransaction to save/restore the settings,
658
 * and during the first transaction within a backend, the value to be saved
659
 * and perhaps restored is indeed invalid.  We have to be able to get
660
 * through AbortTransaction without asserting in case InitPostgres fails.
661
 */
662
void
663
GetUserIdAndSecContext(Oid *userid, int *sec_context)
664
0
{
665
0
  *userid = CurrentUserId;
666
0
  *sec_context = SecurityRestrictionContext;
667
0
}
668
669
void
670
SetUserIdAndSecContext(Oid userid, int sec_context)
671
0
{
672
0
  CurrentUserId = userid;
673
0
  SecurityRestrictionContext = sec_context;
674
0
}
675
676
677
/*
678
 * InLocalUserIdChange - are we inside a local change of CurrentUserId?
679
 */
680
bool
681
InLocalUserIdChange(void)
682
0
{
683
0
  return (SecurityRestrictionContext & SECURITY_LOCAL_USERID_CHANGE) != 0;
684
0
}
685
686
/*
687
 * InSecurityRestrictedOperation - are we inside a security-restricted command?
688
 */
689
bool
690
InSecurityRestrictedOperation(void)
691
0
{
692
0
  return (SecurityRestrictionContext & SECURITY_RESTRICTED_OPERATION) != 0;
693
0
}
694
695
/*
696
 * InNoForceRLSOperation - are we ignoring FORCE ROW LEVEL SECURITY ?
697
 */
698
bool
699
InNoForceRLSOperation(void)
700
0
{
701
0
  return (SecurityRestrictionContext & SECURITY_NOFORCE_RLS) != 0;
702
0
}
703
704
705
/*
706
 * These are obsolete versions of Get/SetUserIdAndSecContext that are
707
 * only provided for bug-compatibility with some rather dubious code in
708
 * pljava.  We allow the userid to be set, but only when not inside a
709
 * security restriction context.
710
 */
711
void
712
GetUserIdAndContext(Oid *userid, bool *sec_def_context)
713
0
{
714
0
  *userid = CurrentUserId;
715
0
  *sec_def_context = InLocalUserIdChange();
716
0
}
717
718
void
719
SetUserIdAndContext(Oid userid, bool sec_def_context)
720
0
{
721
  /* We throw the same error SET ROLE would. */
722
0
  if (InSecurityRestrictedOperation())
723
0
    ereport(ERROR,
724
0
        (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
725
0
         errmsg("cannot set parameter \"%s\" within security-restricted operation",
726
0
            "role")));
727
0
  CurrentUserId = userid;
728
0
  if (sec_def_context)
729
0
    SecurityRestrictionContext |= SECURITY_LOCAL_USERID_CHANGE;
730
0
  else
731
0
    SecurityRestrictionContext &= ~SECURITY_LOCAL_USERID_CHANGE;
732
0
}
733
734
735
/*
736
 * Check whether specified role has explicit REPLICATION privilege
737
 */
738
bool
739
has_rolreplication(Oid roleid)
740
0
{
741
0
  bool    result = false;
742
0
  HeapTuple utup;
743
744
  /* Superusers bypass all permission checking. */
745
0
  if (superuser_arg(roleid))
746
0
    return true;
747
748
0
  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
749
0
  if (HeapTupleIsValid(utup))
750
0
  {
751
0
    result = ((Form_pg_authid) GETSTRUCT(utup))->rolreplication;
752
0
    ReleaseSysCache(utup);
753
0
  }
754
0
  return result;
755
0
}
756
757
/*
758
 * Initialize user identity during normal backend startup
759
 */
760
void
761
InitializeSessionUserId(const char *rolename, Oid roleid,
762
            bool bypass_login_check)
763
0
{
764
0
  HeapTuple roleTup;
765
0
  Form_pg_authid rform;
766
0
  char     *rname;
767
0
  bool    is_superuser;
768
769
  /*
770
   * In a parallel worker, we don't have to do anything here.
771
   * ParallelWorkerMain already set our output variables, and we aren't
772
   * going to enforce either rolcanlogin or rolconnlimit.  Furthermore, we
773
   * don't really want to perform a catalog lookup for the role: we don't
774
   * want to fail if it's been dropped.
775
   */
776
0
  if (InitializingParallelWorker)
777
0
  {
778
0
    Assert(bypass_login_check);
779
0
    return;
780
0
  }
781
782
  /*
783
   * Don't do scans if we're bootstrapping, none of the system catalogs
784
   * exist yet, and they should be owned by postgres anyway.
785
   */
786
0
  Assert(!IsBootstrapProcessingMode());
787
788
  /*
789
   * Make sure syscache entries are flushed for recent catalog changes. This
790
   * allows us to find roles that were created on-the-fly during
791
   * authentication.
792
   */
793
0
  AcceptInvalidationMessages();
794
795
  /*
796
   * Look up the role, either by name if that's given or by OID if not.
797
   */
798
0
  if (rolename != NULL)
799
0
  {
800
0
    roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename));
801
0
    if (!HeapTupleIsValid(roleTup))
802
0
      ereport(FATAL,
803
0
          (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
804
0
           errmsg("role \"%s\" does not exist", rolename)));
805
0
  }
806
0
  else
807
0
  {
808
0
    roleTup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
809
0
    if (!HeapTupleIsValid(roleTup))
810
0
      ereport(FATAL,
811
0
          (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
812
0
           errmsg("role with OID %u does not exist", roleid)));
813
0
  }
814
815
0
  rform = (Form_pg_authid) GETSTRUCT(roleTup);
816
0
  roleid = rform->oid;
817
0
  rname = NameStr(rform->rolname);
818
0
  is_superuser = rform->rolsuper;
819
820
0
  SetAuthenticatedUserId(roleid);
821
822
  /*
823
   * Set SessionUserId and related variables, including "role", via the GUC
824
   * mechanisms.
825
   *
826
   * Note: ideally we would use PGC_S_DYNAMIC_DEFAULT here, so that
827
   * session_authorization could subsequently be changed from
828
   * pg_db_role_setting entries.  Instead, session_authorization in
829
   * pg_db_role_setting has no effect.  Changing that would require solving
830
   * two problems:
831
   *
832
   * 1. If pg_db_role_setting has values for both session_authorization and
833
   * role, we could not be sure which order those would be applied in, and
834
   * it would matter.
835
   *
836
   * 2. Sites may have years-old session_authorization entries.  There's not
837
   * been any particular reason to remove them.  Ending the dormancy of
838
   * those entries could seriously change application behavior, so only a
839
   * major release should do that.
840
   */
841
0
  SetConfigOption("session_authorization", rname,
842
0
          PGC_BACKEND, PGC_S_OVERRIDE);
843
844
  /*
845
   * These next checks are not enforced when in standalone mode, so that
846
   * there is a way to recover from sillinesses like "UPDATE pg_authid SET
847
   * rolcanlogin = false;".
848
   */
849
0
  if (IsUnderPostmaster)
850
0
  {
851
    /*
852
     * Is role allowed to login at all?  (But background workers can
853
     * override this by setting bypass_login_check.)
854
     */
855
0
    if (!bypass_login_check && !rform->rolcanlogin)
856
0
      ereport(FATAL,
857
0
          (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
858
0
           errmsg("role \"%s\" is not permitted to log in",
859
0
              rname)));
860
861
    /*
862
     * Check connection limit for this role.  We enforce the limit only
863
     * for regular backends, since other process types have their own
864
     * PGPROC pools.
865
     *
866
     * There is a race condition here --- we create our PGPROC before
867
     * checking for other PGPROCs.  If two backends did this at about the
868
     * same time, they might both think they were over the limit, while
869
     * ideally one should succeed and one fail.  Getting that to work
870
     * exactly seems more trouble than it is worth, however; instead we
871
     * just document that the connection limit is approximate.
872
     */
873
0
    if (rform->rolconnlimit >= 0 &&
874
0
      AmRegularBackendProcess() &&
875
0
      !is_superuser &&
876
0
      CountUserBackends(roleid) > rform->rolconnlimit)
877
0
      ereport(FATAL,
878
0
          (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
879
0
           errmsg("too many connections for role \"%s\"",
880
0
              rname)));
881
0
  }
882
883
0
  ReleaseSysCache(roleTup);
884
0
}
885
886
887
/*
888
 * Initialize user identity during special backend startup
889
 */
890
void
891
InitializeSessionUserIdStandalone(void)
892
0
{
893
  /*
894
   * This function should only be called in single-user mode, in autovacuum
895
   * workers, in slot sync worker and in background workers.
896
   */
897
0
  Assert(!IsUnderPostmaster || AmAutoVacuumWorkerProcess() ||
898
0
       AmLogicalSlotSyncWorkerProcess() || AmBackgroundWorkerProcess());
899
900
  /* call only once */
901
0
  Assert(!OidIsValid(AuthenticatedUserId));
902
903
0
  AuthenticatedUserId = BOOTSTRAP_SUPERUSERID;
904
905
  /*
906
   * XXX Ideally we'd do this via SetConfigOption("session_authorization"),
907
   * but we lack the role name needed to do that, and we can't fetch it
908
   * because one reason for this special case is to be able to start up even
909
   * if something's happened to the BOOTSTRAP_SUPERUSERID's pg_authid row.
910
   * Since we don't set the GUC itself, C code will see the value as NULL,
911
   * and current_setting() will report an empty string within this session.
912
   */
913
0
  SetSessionAuthorization(BOOTSTRAP_SUPERUSERID, true);
914
915
  /* We could do SetConfigOption("role"), but let's be consistent */
916
0
  SetCurrentRoleId(InvalidOid, false);
917
0
}
918
919
/*
920
 * Initialize the system user.
921
 *
922
 * This is built as auth_method:authn_id.
923
 */
924
void
925
InitializeSystemUser(const char *authn_id, const char *auth_method)
926
0
{
927
0
  char     *system_user;
928
929
  /* call only once */
930
0
  Assert(SystemUser == NULL);
931
932
  /*
933
   * InitializeSystemUser should be called only when authn_id is not NULL,
934
   * meaning that auth_method is valid.
935
   */
936
0
  Assert(authn_id != NULL);
937
938
0
  system_user = psprintf("%s:%s", auth_method, authn_id);
939
940
  /* Store SystemUser in long-lived storage */
941
0
  SystemUser = MemoryContextStrdup(TopMemoryContext, system_user);
942
0
  pfree(system_user);
943
0
}
944
945
/*
946
 * SQL-function SYSTEM_USER
947
 */
948
Datum
949
system_user(PG_FUNCTION_ARGS)
950
0
{
951
0
  const char *sysuser = GetSystemUser();
952
953
0
  if (sysuser)
954
0
    PG_RETURN_DATUM(CStringGetTextDatum(sysuser));
955
0
  else
956
0
    PG_RETURN_NULL();
957
0
}
958
959
/*
960
 * Change session auth ID while running
961
 *
962
 * The SQL standard says that SET SESSION AUTHORIZATION implies SET ROLE NONE.
963
 * We mechanize that at higher levels not here, because this is the GUC
964
 * assign hook for "session_authorization", and it must be commutative with
965
 * SetCurrentRoleId (the hook for "role") because guc.c provides no guarantees
966
 * which will run first during cases such as transaction rollback.  Therefore,
967
 * we update derived state (OuterUserId/CurrentUserId/is_superuser) only if
968
 * !SetRoleIsActive.
969
 */
970
void
971
SetSessionAuthorization(Oid userid, bool is_superuser)
972
0
{
973
0
  SetSessionUserId(userid, is_superuser);
974
975
0
  if (!SetRoleIsActive)
976
0
    SetOuterUserId(userid, is_superuser);
977
0
}
978
979
/*
980
 * Report current role id
981
 *    This follows the semantics of SET ROLE, ie return the outer-level ID
982
 *    not the current effective ID, and return InvalidOid when the setting
983
 *    is logically SET ROLE NONE.
984
 */
985
Oid
986
GetCurrentRoleId(void)
987
0
{
988
0
  if (SetRoleIsActive)
989
0
    return OuterUserId;
990
0
  else
991
0
    return InvalidOid;
992
0
}
993
994
/*
995
 * Change Role ID while running (SET ROLE)
996
 *
997
 * If roleid is InvalidOid, we are doing SET ROLE NONE: revert to the
998
 * session user authorization.  In this case the is_superuser argument
999
 * is ignored.
1000
 *
1001
 * When roleid is not InvalidOid, the caller must have checked whether
1002
 * the session user has permission to become that role.  (We cannot check
1003
 * here because this routine must be able to execute in a failed transaction
1004
 * to restore a prior value of the ROLE GUC variable.)
1005
 */
1006
void
1007
SetCurrentRoleId(Oid roleid, bool is_superuser)
1008
0
{
1009
  /*
1010
   * Get correct info if it's SET ROLE NONE
1011
   *
1012
   * If SessionUserId hasn't been set yet, do nothing beyond updating
1013
   * SetRoleIsActive --- the eventual SetSessionAuthorization call will
1014
   * update the derived state.  This is needed since we will get called
1015
   * during GUC initialization.
1016
   */
1017
0
  if (!OidIsValid(roleid))
1018
0
  {
1019
0
    SetRoleIsActive = false;
1020
1021
0
    if (!OidIsValid(SessionUserId))
1022
0
      return;
1023
1024
0
    roleid = SessionUserId;
1025
0
    is_superuser = SessionUserIsSuperuser;
1026
0
  }
1027
0
  else
1028
0
    SetRoleIsActive = true;
1029
1030
0
  SetOuterUserId(roleid, is_superuser);
1031
0
}
1032
1033
1034
/*
1035
 * Get user name from user oid, returns NULL for nonexistent roleid if noerr
1036
 * is true.
1037
 */
1038
char *
1039
GetUserNameFromId(Oid roleid, bool noerr)
1040
0
{
1041
0
  HeapTuple tuple;
1042
0
  char     *result;
1043
1044
0
  tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
1045
0
  if (!HeapTupleIsValid(tuple))
1046
0
  {
1047
0
    if (!noerr)
1048
0
      ereport(ERROR,
1049
0
          (errcode(ERRCODE_UNDEFINED_OBJECT),
1050
0
           errmsg("invalid role OID: %u", roleid)));
1051
0
    result = NULL;
1052
0
  }
1053
0
  else
1054
0
  {
1055
0
    result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
1056
0
    ReleaseSysCache(tuple);
1057
0
  }
1058
0
  return result;
1059
0
}
1060
1061
/* ------------------------------------------------------------------------
1062
 *        Client connection state shared with parallel workers
1063
 *
1064
 * ClientConnectionInfo contains pieces of information about the client that
1065
 * need to be synced to parallel workers when they initialize.
1066
 *-------------------------------------------------------------------------
1067
 */
1068
1069
ClientConnectionInfo MyClientConnectionInfo;
1070
1071
/*
1072
 * Intermediate representation of ClientConnectionInfo for easier
1073
 * serialization.  Variable-length fields are allocated right after this
1074
 * header.
1075
 */
1076
typedef struct SerializedClientConnectionInfo
1077
{
1078
  int32   authn_id_len; /* strlen(authn_id), or -1 if NULL */
1079
  UserAuth  auth_method;
1080
} SerializedClientConnectionInfo;
1081
1082
/*
1083
 * Calculate the space needed to serialize MyClientConnectionInfo.
1084
 */
1085
Size
1086
EstimateClientConnectionInfoSpace(void)
1087
0
{
1088
0
  Size    size = 0;
1089
1090
0
  size = add_size(size, sizeof(SerializedClientConnectionInfo));
1091
1092
0
  if (MyClientConnectionInfo.authn_id)
1093
0
    size = add_size(size, strlen(MyClientConnectionInfo.authn_id) + 1);
1094
1095
0
  return size;
1096
0
}
1097
1098
/*
1099
 * Serialize MyClientConnectionInfo for use by parallel workers.
1100
 */
1101
void
1102
SerializeClientConnectionInfo(Size maxsize, char *start_address)
1103
0
{
1104
0
  SerializedClientConnectionInfo serialized = {0};
1105
1106
0
  serialized.authn_id_len = -1;
1107
0
  serialized.auth_method = MyClientConnectionInfo.auth_method;
1108
1109
0
  if (MyClientConnectionInfo.authn_id)
1110
0
    serialized.authn_id_len = strlen(MyClientConnectionInfo.authn_id);
1111
1112
  /* Copy serialized representation to buffer */
1113
0
  Assert(maxsize >= sizeof(serialized));
1114
0
  memcpy(start_address, &serialized, sizeof(serialized));
1115
1116
0
  maxsize -= sizeof(serialized);
1117
0
  start_address += sizeof(serialized);
1118
1119
  /* Copy authn_id into the space after the struct */
1120
0
  if (serialized.authn_id_len >= 0)
1121
0
  {
1122
0
    Assert(maxsize >= (serialized.authn_id_len + 1));
1123
0
    memcpy(start_address,
1124
0
         MyClientConnectionInfo.authn_id,
1125
    /* include the NULL terminator to ease deserialization */
1126
0
         serialized.authn_id_len + 1);
1127
0
  }
1128
0
}
1129
1130
/*
1131
 * Restore MyClientConnectionInfo from its serialized representation.
1132
 */
1133
void
1134
RestoreClientConnectionInfo(char *conninfo)
1135
0
{
1136
0
  SerializedClientConnectionInfo serialized;
1137
1138
0
  memcpy(&serialized, conninfo, sizeof(serialized));
1139
1140
  /* Copy the fields back into place */
1141
0
  MyClientConnectionInfo.authn_id = NULL;
1142
0
  MyClientConnectionInfo.auth_method = serialized.auth_method;
1143
1144
0
  if (serialized.authn_id_len >= 0)
1145
0
  {
1146
0
    char     *authn_id;
1147
1148
0
    authn_id = conninfo + sizeof(serialized);
1149
0
    MyClientConnectionInfo.authn_id = MemoryContextStrdup(TopMemoryContext,
1150
0
                                authn_id);
1151
0
  }
1152
0
}
1153
1154
1155
/*-------------------------------------------------------------------------
1156
 *        Interlock-file support
1157
 *
1158
 * These routines are used to create both a data-directory lockfile
1159
 * ($DATADIR/postmaster.pid) and Unix-socket-file lockfiles ($SOCKFILE.lock).
1160
 * Both kinds of files contain the same info initially, although we can add
1161
 * more information to a data-directory lockfile after it's created, using
1162
 * AddToDataDirLockFile().  See pidfile.h for documentation of the contents
1163
 * of these lockfiles.
1164
 *
1165
 * On successful lockfile creation, a proc_exit callback to remove the
1166
 * lockfile is automatically created.
1167
 *-------------------------------------------------------------------------
1168
 */
1169
1170
/*
1171
 * proc_exit callback to remove lockfiles.
1172
 */
1173
static void
1174
UnlinkLockFiles(int status, Datum arg)
1175
0
{
1176
0
  ListCell   *l;
1177
1178
0
  foreach(l, lock_files)
1179
0
  {
1180
0
    char     *curfile = (char *) lfirst(l);
1181
1182
0
    unlink(curfile);
1183
    /* Should we complain if the unlink fails? */
1184
0
  }
1185
  /* Since we're about to exit, no need to reclaim storage */
1186
0
  lock_files = NIL;
1187
1188
  /*
1189
   * Lock file removal should always be the last externally visible action
1190
   * of a postmaster or standalone backend, while we won't come here at all
1191
   * when exiting postmaster child processes.  Therefore, this is a good
1192
   * place to log completion of shutdown.  We could alternatively teach
1193
   * proc_exit() to do it, but that seems uglier.  In a standalone backend,
1194
   * use NOTICE elevel to be less chatty.
1195
   */
1196
0
  ereport(IsPostmasterEnvironment ? LOG : NOTICE,
1197
0
      (errmsg("database system is shut down")));
1198
0
}
1199
1200
/*
1201
 * Create a lockfile.
1202
 *
1203
 * filename is the path name of the lockfile to create.
1204
 * amPostmaster is used to determine how to encode the output PID.
1205
 * socketDir is the Unix socket directory path to include (possibly empty).
1206
 * isDDLock and refName are used to determine what error message to produce.
1207
 */
1208
static void
1209
CreateLockFile(const char *filename, bool amPostmaster,
1210
         const char *socketDir,
1211
         bool isDDLock, const char *refName)
1212
0
{
1213
0
  int     fd;
1214
0
  char    buffer[MAXPGPATH * 2 + 256];
1215
0
  int     ntries;
1216
0
  int     len;
1217
0
  int     encoded_pid;
1218
0
  pid_t   other_pid;
1219
0
  pid_t   my_pid,
1220
0
        my_p_pid,
1221
0
        my_gp_pid;
1222
0
  const char *envvar;
1223
1224
  /*
1225
   * If the PID in the lockfile is our own PID or our parent's or
1226
   * grandparent's PID, then the file must be stale (probably left over from
1227
   * a previous system boot cycle).  We need to check this because of the
1228
   * likelihood that a reboot will assign exactly the same PID as we had in
1229
   * the previous reboot, or one that's only one or two counts larger and
1230
   * hence the lockfile's PID now refers to an ancestor shell process.  We
1231
   * allow pg_ctl to pass down its parent shell PID (our grandparent PID)
1232
   * via the environment variable PG_GRANDPARENT_PID; this is so that
1233
   * launching the postmaster via pg_ctl can be just as reliable as
1234
   * launching it directly.  There is no provision for detecting
1235
   * further-removed ancestor processes, but if the init script is written
1236
   * carefully then all but the immediate parent shell will be root-owned
1237
   * processes and so the kill test will fail with EPERM.  Note that we
1238
   * cannot get a false negative this way, because an existing postmaster
1239
   * would surely never launch a competing postmaster or pg_ctl process
1240
   * directly.
1241
   */
1242
0
  my_pid = getpid();
1243
1244
0
#ifndef WIN32
1245
0
  my_p_pid = getppid();
1246
#else
1247
1248
  /*
1249
   * Windows hasn't got getppid(), but doesn't need it since it's not using
1250
   * real kill() either...
1251
   */
1252
  my_p_pid = 0;
1253
#endif
1254
1255
0
  envvar = getenv("PG_GRANDPARENT_PID");
1256
0
  if (envvar)
1257
0
    my_gp_pid = atoi(envvar);
1258
0
  else
1259
0
    my_gp_pid = 0;
1260
1261
  /*
1262
   * We need a loop here because of race conditions.  But don't loop forever
1263
   * (for example, a non-writable $PGDATA directory might cause a failure
1264
   * that won't go away).  100 tries seems like plenty.
1265
   */
1266
0
  for (ntries = 0;; ntries++)
1267
0
  {
1268
    /*
1269
     * Try to create the lock file --- O_EXCL makes this atomic.
1270
     *
1271
     * Think not to make the file protection weaker than 0600/0640.  See
1272
     * comments below.
1273
     */
1274
0
    fd = open(filename, O_RDWR | O_CREAT | O_EXCL, pg_file_create_mode);
1275
0
    if (fd >= 0)
1276
0
      break;       /* Success; exit the retry loop */
1277
1278
    /*
1279
     * Couldn't create the pid file. Probably it already exists.
1280
     */
1281
0
    if ((errno != EEXIST && errno != EACCES) || ntries > 100)
1282
0
      ereport(FATAL,
1283
0
          (errcode_for_file_access(),
1284
0
           errmsg("could not create lock file \"%s\": %m",
1285
0
              filename)));
1286
1287
    /*
1288
     * Read the file to get the old owner's PID.  Note race condition
1289
     * here: file might have been deleted since we tried to create it.
1290
     */
1291
0
    fd = open(filename, O_RDONLY, pg_file_create_mode);
1292
0
    if (fd < 0)
1293
0
    {
1294
0
      if (errno == ENOENT)
1295
0
        continue;   /* race condition; try again */
1296
0
      ereport(FATAL,
1297
0
          (errcode_for_file_access(),
1298
0
           errmsg("could not open lock file \"%s\": %m",
1299
0
              filename)));
1300
0
    }
1301
0
    pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_READ);
1302
0
    if ((len = read(fd, buffer, sizeof(buffer) - 1)) < 0)
1303
0
      ereport(FATAL,
1304
0
          (errcode_for_file_access(),
1305
0
           errmsg("could not read lock file \"%s\": %m",
1306
0
              filename)));
1307
0
    pgstat_report_wait_end();
1308
0
    close(fd);
1309
1310
0
    if (len == 0)
1311
0
    {
1312
0
      ereport(FATAL,
1313
0
          (errcode(ERRCODE_LOCK_FILE_EXISTS),
1314
0
           errmsg("lock file \"%s\" is empty", filename),
1315
0
           errhint("Either another server is starting, or the lock file is the remnant of a previous server startup crash.")));
1316
0
    }
1317
1318
0
    buffer[len] = '\0';
1319
0
    encoded_pid = atoi(buffer);
1320
1321
    /* if pid < 0, the pid is for postgres, not postmaster */
1322
0
    other_pid = (pid_t) (encoded_pid < 0 ? -encoded_pid : encoded_pid);
1323
1324
0
    if (other_pid <= 0)
1325
0
      elog(FATAL, "bogus data in lock file \"%s\": \"%s\"",
1326
0
         filename, buffer);
1327
1328
    /*
1329
     * Check to see if the other process still exists
1330
     *
1331
     * Per discussion above, my_pid, my_p_pid, and my_gp_pid can be
1332
     * ignored as false matches.
1333
     *
1334
     * Normally kill() will fail with ESRCH if the given PID doesn't
1335
     * exist.
1336
     *
1337
     * We can treat the EPERM-error case as okay because that error
1338
     * implies that the existing process has a different userid than we
1339
     * do, which means it cannot be a competing postmaster.  A postmaster
1340
     * cannot successfully attach to a data directory owned by a userid
1341
     * other than its own, as enforced in checkDataDir(). Also, since we
1342
     * create the lockfiles mode 0600/0640, we'd have failed above if the
1343
     * lockfile belonged to another userid --- which means that whatever
1344
     * process kill() is reporting about isn't the one that made the
1345
     * lockfile.  (NOTE: this last consideration is the only one that
1346
     * keeps us from blowing away a Unix socket file belonging to an
1347
     * instance of Postgres being run by someone else, at least on
1348
     * machines where /tmp hasn't got a stickybit.)
1349
     */
1350
0
    if (other_pid != my_pid && other_pid != my_p_pid &&
1351
0
      other_pid != my_gp_pid)
1352
0
    {
1353
0
      if (kill(other_pid, 0) == 0 ||
1354
0
        (errno != ESRCH && errno != EPERM))
1355
0
      {
1356
        /* lockfile belongs to a live process */
1357
0
        ereport(FATAL,
1358
0
            (errcode(ERRCODE_LOCK_FILE_EXISTS),
1359
0
             errmsg("lock file \"%s\" already exists",
1360
0
                filename),
1361
0
             isDDLock ?
1362
0
             (encoded_pid < 0 ?
1363
0
              errhint("Is another postgres (PID %d) running in data directory \"%s\"?",
1364
0
                  (int) other_pid, refName) :
1365
0
              errhint("Is another postmaster (PID %d) running in data directory \"%s\"?",
1366
0
                  (int) other_pid, refName)) :
1367
0
             (encoded_pid < 0 ?
1368
0
              errhint("Is another postgres (PID %d) using socket file \"%s\"?",
1369
0
                  (int) other_pid, refName) :
1370
0
              errhint("Is another postmaster (PID %d) using socket file \"%s\"?",
1371
0
                  (int) other_pid, refName))));
1372
0
      }
1373
0
    }
1374
1375
    /*
1376
     * No, the creating process did not exist.  However, it could be that
1377
     * the postmaster crashed (or more likely was kill -9'd by a clueless
1378
     * admin) but has left orphan backends behind.  Check for this by
1379
     * looking to see if there is an associated shmem segment that is
1380
     * still in use.
1381
     *
1382
     * Note: because postmaster.pid is written in multiple steps, we might
1383
     * not find the shmem ID values in it; we can't treat that as an
1384
     * error.
1385
     */
1386
0
    if (isDDLock)
1387
0
    {
1388
0
      char     *ptr = buffer;
1389
0
      unsigned long id1,
1390
0
            id2;
1391
0
      int     lineno;
1392
1393
0
      for (lineno = 1; lineno < LOCK_FILE_LINE_SHMEM_KEY; lineno++)
1394
0
      {
1395
0
        if ((ptr = strchr(ptr, '\n')) == NULL)
1396
0
          break;
1397
0
        ptr++;
1398
0
      }
1399
1400
0
      if (ptr != NULL &&
1401
0
        sscanf(ptr, "%lu %lu", &id1, &id2) == 2)
1402
0
      {
1403
0
        if (PGSharedMemoryIsInUse(id1, id2))
1404
0
          ereport(FATAL,
1405
0
              (errcode(ERRCODE_LOCK_FILE_EXISTS),
1406
0
               errmsg("pre-existing shared memory block (key %lu, ID %lu) is still in use",
1407
0
                  id1, id2),
1408
0
               errhint("Terminate any old server processes associated with data directory \"%s\".",
1409
0
                   refName)));
1410
0
      }
1411
0
    }
1412
1413
    /*
1414
     * Looks like nobody's home.  Unlink the file and try again to create
1415
     * it.  Need a loop because of possible race condition against other
1416
     * would-be creators.
1417
     */
1418
0
    if (unlink(filename) < 0)
1419
0
      ereport(FATAL,
1420
0
          (errcode_for_file_access(),
1421
0
           errmsg("could not remove old lock file \"%s\": %m",
1422
0
              filename),
1423
0
           errhint("The file seems accidentally left over, but "
1424
0
               "it could not be removed. Please remove the file "
1425
0
               "by hand and try again.")));
1426
0
  }
1427
1428
  /*
1429
   * Successfully created the file, now fill it.  See comment in pidfile.h
1430
   * about the contents.  Note that we write the same first five lines into
1431
   * both datadir and socket lockfiles; although more stuff may get added to
1432
   * the datadir lockfile later.
1433
   */
1434
0
  snprintf(buffer, sizeof(buffer), "%d\n%s\n" INT64_FORMAT "\n%d\n%s\n",
1435
0
       amPostmaster ? (int) my_pid : -((int) my_pid),
1436
0
       DataDir,
1437
0
       MyStartTime,
1438
0
       PostPortNumber,
1439
0
       socketDir);
1440
1441
  /*
1442
   * In a standalone backend, the next line (LOCK_FILE_LINE_LISTEN_ADDR)
1443
   * will never receive data, so fill it in as empty now.
1444
   */
1445
0
  if (isDDLock && !amPostmaster)
1446
0
    strlcat(buffer, "\n", sizeof(buffer));
1447
1448
0
  errno = 0;
1449
0
  pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_WRITE);
1450
0
  if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
1451
0
  {
1452
0
    int     save_errno = errno;
1453
1454
0
    close(fd);
1455
0
    unlink(filename);
1456
    /* if write didn't set errno, assume problem is no disk space */
1457
0
    errno = save_errno ? save_errno : ENOSPC;
1458
0
    ereport(FATAL,
1459
0
        (errcode_for_file_access(),
1460
0
         errmsg("could not write lock file \"%s\": %m", filename)));
1461
0
  }
1462
0
  pgstat_report_wait_end();
1463
1464
0
  pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_SYNC);
1465
0
  if (pg_fsync(fd) != 0)
1466
0
  {
1467
0
    int     save_errno = errno;
1468
1469
0
    close(fd);
1470
0
    unlink(filename);
1471
0
    errno = save_errno;
1472
0
    ereport(FATAL,
1473
0
        (errcode_for_file_access(),
1474
0
         errmsg("could not write lock file \"%s\": %m", filename)));
1475
0
  }
1476
0
  pgstat_report_wait_end();
1477
0
  if (close(fd) != 0)
1478
0
  {
1479
0
    int     save_errno = errno;
1480
1481
0
    unlink(filename);
1482
0
    errno = save_errno;
1483
0
    ereport(FATAL,
1484
0
        (errcode_for_file_access(),
1485
0
         errmsg("could not write lock file \"%s\": %m", filename)));
1486
0
  }
1487
1488
  /*
1489
   * Arrange to unlink the lock file(s) at proc_exit.  If this is the first
1490
   * one, set up the on_proc_exit function to do it; then add this lock file
1491
   * to the list of files to unlink.
1492
   */
1493
0
  if (lock_files == NIL)
1494
0
    on_proc_exit(UnlinkLockFiles, 0);
1495
1496
  /*
1497
   * Use lcons so that the lock files are unlinked in reverse order of
1498
   * creation; this is critical!
1499
   */
1500
0
  lock_files = lcons(pstrdup(filename), lock_files);
1501
0
}
1502
1503
/*
1504
 * Create the data directory lockfile.
1505
 *
1506
 * When this is called, we must have already switched the working
1507
 * directory to DataDir, so we can just use a relative path.  This
1508
 * helps ensure that we are locking the directory we should be.
1509
 *
1510
 * Note that the socket directory path line is initially written as empty.
1511
 * postmaster.c will rewrite it upon creating the first Unix socket.
1512
 */
1513
void
1514
CreateDataDirLockFile(bool amPostmaster)
1515
0
{
1516
0
  CreateLockFile(DIRECTORY_LOCK_FILE, amPostmaster, "", true, DataDir);
1517
0
}
1518
1519
/*
1520
 * Create a lockfile for the specified Unix socket file.
1521
 */
1522
void
1523
CreateSocketLockFile(const char *socketfile, bool amPostmaster,
1524
           const char *socketDir)
1525
0
{
1526
0
  char    lockfile[MAXPGPATH];
1527
1528
0
  snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile);
1529
0
  CreateLockFile(lockfile, amPostmaster, socketDir, false, socketfile);
1530
0
}
1531
1532
/*
1533
 * TouchSocketLockFiles -- mark socket lock files as recently accessed
1534
 *
1535
 * This routine should be called every so often to ensure that the socket
1536
 * lock files have a recent mod or access date.  That saves them
1537
 * from being removed by overenthusiastic /tmp-directory-cleaner daemons.
1538
 * (Another reason we should never have put the socket file in /tmp...)
1539
 */
1540
void
1541
TouchSocketLockFiles(void)
1542
0
{
1543
0
  ListCell   *l;
1544
1545
0
  foreach(l, lock_files)
1546
0
  {
1547
0
    char     *socketLockFile = (char *) lfirst(l);
1548
1549
    /* No need to touch the data directory lock file, we trust */
1550
0
    if (strcmp(socketLockFile, DIRECTORY_LOCK_FILE) == 0)
1551
0
      continue;
1552
1553
    /* we just ignore any error here */
1554
0
    (void) utime(socketLockFile, NULL);
1555
0
  }
1556
0
}
1557
1558
1559
/*
1560
 * Add (or replace) a line in the data directory lock file.
1561
 * The given string should not include a trailing newline.
1562
 *
1563
 * Note: because we don't truncate the file, if we were to rewrite a line
1564
 * with less data than it had before, there would be garbage after the last
1565
 * line.  While we could fix that by adding a truncate call, that would make
1566
 * the file update non-atomic, which we'd rather avoid.  Therefore, callers
1567
 * should endeavor never to shorten a line once it's been written.
1568
 */
1569
void
1570
AddToDataDirLockFile(int target_line, const char *str)
1571
0
{
1572
0
  int     fd;
1573
0
  int     len;
1574
0
  int     lineno;
1575
0
  char     *srcptr;
1576
0
  char     *destptr;
1577
0
  char    srcbuffer[BLCKSZ];
1578
0
  char    destbuffer[BLCKSZ];
1579
1580
0
  fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
1581
0
  if (fd < 0)
1582
0
  {
1583
0
    ereport(LOG,
1584
0
        (errcode_for_file_access(),
1585
0
         errmsg("could not open file \"%s\": %m",
1586
0
            DIRECTORY_LOCK_FILE)));
1587
0
    return;
1588
0
  }
1589
0
  pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ);
1590
0
  len = read(fd, srcbuffer, sizeof(srcbuffer) - 1);
1591
0
  pgstat_report_wait_end();
1592
0
  if (len < 0)
1593
0
  {
1594
0
    ereport(LOG,
1595
0
        (errcode_for_file_access(),
1596
0
         errmsg("could not read from file \"%s\": %m",
1597
0
            DIRECTORY_LOCK_FILE)));
1598
0
    close(fd);
1599
0
    return;
1600
0
  }
1601
0
  srcbuffer[len] = '\0';
1602
1603
  /*
1604
   * Advance over lines we are not supposed to rewrite, then copy them to
1605
   * destbuffer.
1606
   */
1607
0
  srcptr = srcbuffer;
1608
0
  for (lineno = 1; lineno < target_line; lineno++)
1609
0
  {
1610
0
    char     *eol = strchr(srcptr, '\n');
1611
1612
0
    if (eol == NULL)
1613
0
      break;       /* not enough lines in file yet */
1614
0
    srcptr = eol + 1;
1615
0
  }
1616
0
  memcpy(destbuffer, srcbuffer, srcptr - srcbuffer);
1617
0
  destptr = destbuffer + (srcptr - srcbuffer);
1618
1619
  /*
1620
   * Fill in any missing lines before the target line, in case lines are
1621
   * added to the file out of order.
1622
   */
1623
0
  for (; lineno < target_line; lineno++)
1624
0
  {
1625
0
    if (destptr < destbuffer + sizeof(destbuffer))
1626
0
      *destptr++ = '\n';
1627
0
  }
1628
1629
  /*
1630
   * Write or rewrite the target line.
1631
   */
1632
0
  snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s\n", str);
1633
0
  destptr += strlen(destptr);
1634
1635
  /*
1636
   * If there are more lines in the old file, append them to destbuffer.
1637
   */
1638
0
  if ((srcptr = strchr(srcptr, '\n')) != NULL)
1639
0
  {
1640
0
    srcptr++;
1641
0
    snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s",
1642
0
         srcptr);
1643
0
  }
1644
1645
  /*
1646
   * And rewrite the data.  Since we write in a single kernel call, this
1647
   * update should appear atomic to onlookers.
1648
   */
1649
0
  len = strlen(destbuffer);
1650
0
  errno = 0;
1651
0
  pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE);
1652
0
  if (pg_pwrite(fd, destbuffer, len, 0) != len)
1653
0
  {
1654
0
    pgstat_report_wait_end();
1655
    /* if write didn't set errno, assume problem is no disk space */
1656
0
    if (errno == 0)
1657
0
      errno = ENOSPC;
1658
0
    ereport(LOG,
1659
0
        (errcode_for_file_access(),
1660
0
         errmsg("could not write to file \"%s\": %m",
1661
0
            DIRECTORY_LOCK_FILE)));
1662
0
    close(fd);
1663
0
    return;
1664
0
  }
1665
0
  pgstat_report_wait_end();
1666
0
  pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC);
1667
0
  if (pg_fsync(fd) != 0)
1668
0
  {
1669
0
    ereport(LOG,
1670
0
        (errcode_for_file_access(),
1671
0
         errmsg("could not write to file \"%s\": %m",
1672
0
            DIRECTORY_LOCK_FILE)));
1673
0
  }
1674
0
  pgstat_report_wait_end();
1675
0
  if (close(fd) != 0)
1676
0
  {
1677
0
    ereport(LOG,
1678
0
        (errcode_for_file_access(),
1679
0
         errmsg("could not write to file \"%s\": %m",
1680
0
            DIRECTORY_LOCK_FILE)));
1681
0
  }
1682
0
}
1683
1684
1685
/*
1686
 * Recheck that the data directory lock file still exists with expected
1687
 * content.  Return true if the lock file appears OK, false if it isn't.
1688
 *
1689
 * We call this periodically in the postmaster.  The idea is that if the
1690
 * lock file has been removed or replaced by another postmaster, we should
1691
 * do a panic database shutdown.  Therefore, we should return true if there
1692
 * is any doubt: we do not want to cause a panic shutdown unnecessarily.
1693
 * Transient failures like EINTR or ENFILE should not cause us to fail.
1694
 * (If there really is something wrong, we'll detect it on a future recheck.)
1695
 */
1696
bool
1697
RecheckDataDirLockFile(void)
1698
0
{
1699
0
  int     fd;
1700
0
  int     len;
1701
0
  long    file_pid;
1702
0
  char    buffer[BLCKSZ];
1703
1704
0
  fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
1705
0
  if (fd < 0)
1706
0
  {
1707
    /*
1708
     * There are many foreseeable false-positive error conditions.  For
1709
     * safety, fail only on enumerated clearly-something-is-wrong
1710
     * conditions.
1711
     */
1712
0
    switch (errno)
1713
0
    {
1714
0
      case ENOENT:
1715
0
      case ENOTDIR:
1716
        /* disaster */
1717
0
        ereport(LOG,
1718
0
            (errcode_for_file_access(),
1719
0
             errmsg("could not open file \"%s\": %m",
1720
0
                DIRECTORY_LOCK_FILE)));
1721
0
        return false;
1722
0
      default:
1723
        /* non-fatal, at least for now */
1724
0
        ereport(LOG,
1725
0
            (errcode_for_file_access(),
1726
0
             errmsg("could not open file \"%s\": %m; continuing anyway",
1727
0
                DIRECTORY_LOCK_FILE)));
1728
0
        return true;
1729
0
    }
1730
0
  }
1731
0
  pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ);
1732
0
  len = read(fd, buffer, sizeof(buffer) - 1);
1733
0
  pgstat_report_wait_end();
1734
0
  if (len < 0)
1735
0
  {
1736
0
    ereport(LOG,
1737
0
        (errcode_for_file_access(),
1738
0
         errmsg("could not read from file \"%s\": %m",
1739
0
            DIRECTORY_LOCK_FILE)));
1740
0
    close(fd);
1741
0
    return true;     /* treat read failure as nonfatal */
1742
0
  }
1743
0
  buffer[len] = '\0';
1744
0
  close(fd);
1745
0
  file_pid = atol(buffer);
1746
0
  if (file_pid == getpid())
1747
0
    return true;     /* all is well */
1748
1749
  /* Trouble: someone's overwritten the lock file */
1750
0
  ereport(LOG,
1751
0
      (errmsg("lock file \"%s\" contains wrong PID: %ld instead of %ld",
1752
0
          DIRECTORY_LOCK_FILE, file_pid, (long) getpid())));
1753
0
  return false;
1754
0
}
1755
1756
1757
/*-------------------------------------------------------------------------
1758
 *        Version checking support
1759
 *-------------------------------------------------------------------------
1760
 */
1761
1762
/*
1763
 * Determine whether the PG_VERSION file in directory `path' indicates
1764
 * a data version compatible with the version of this program.
1765
 *
1766
 * If compatible, return. Otherwise, ereport(FATAL).
1767
 */
1768
void
1769
ValidatePgVersion(const char *path)
1770
0
{
1771
0
  char    full_path[MAXPGPATH];
1772
0
  FILE     *file;
1773
0
  int     ret;
1774
0
  long    file_major;
1775
0
  long    my_major;
1776
0
  char     *endptr;
1777
0
  char    file_version_string[64];
1778
0
  const char *my_version_string = PG_VERSION;
1779
1780
0
  my_major = strtol(my_version_string, &endptr, 10);
1781
1782
0
  snprintf(full_path, sizeof(full_path), "%s/PG_VERSION", path);
1783
1784
0
  file = AllocateFile(full_path, "r");
1785
0
  if (!file)
1786
0
  {
1787
0
    if (errno == ENOENT)
1788
0
      ereport(FATAL,
1789
0
          (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1790
0
           errmsg("\"%s\" is not a valid data directory",
1791
0
              path),
1792
0
           errdetail("File \"%s\" is missing.", full_path)));
1793
0
    else
1794
0
      ereport(FATAL,
1795
0
          (errcode_for_file_access(),
1796
0
           errmsg("could not open file \"%s\": %m", full_path)));
1797
0
  }
1798
1799
0
  file_version_string[0] = '\0';
1800
0
  ret = fscanf(file, "%63s", file_version_string);
1801
0
  file_major = strtol(file_version_string, &endptr, 10);
1802
1803
0
  if (ret != 1 || endptr == file_version_string)
1804
0
    ereport(FATAL,
1805
0
        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1806
0
         errmsg("\"%s\" is not a valid data directory",
1807
0
            path),
1808
0
         errdetail("File \"%s\" does not contain valid data.",
1809
0
               full_path),
1810
0
         errhint("You might need to initdb.")));
1811
1812
0
  FreeFile(file);
1813
1814
0
  if (my_major != file_major)
1815
0
    ereport(FATAL,
1816
0
        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1817
0
         errmsg("database files are incompatible with server"),
1818
0
         errdetail("The data directory was initialized by PostgreSQL version %s, "
1819
0
               "which is not compatible with this version %s.",
1820
0
               file_version_string, my_version_string)));
1821
0
}
1822
1823
/*-------------------------------------------------------------------------
1824
 *        Library preload support
1825
 *-------------------------------------------------------------------------
1826
 */
1827
1828
/*
1829
 * GUC variables: lists of library names to be preloaded at postmaster
1830
 * start and at backend start
1831
 */
1832
char     *session_preload_libraries_string = NULL;
1833
char     *shared_preload_libraries_string = NULL;
1834
char     *local_preload_libraries_string = NULL;
1835
1836
/* Flag telling that we are loading shared_preload_libraries */
1837
bool    process_shared_preload_libraries_in_progress = false;
1838
bool    process_shared_preload_libraries_done = false;
1839
1840
shmem_request_hook_type shmem_request_hook = NULL;
1841
bool    process_shmem_requests_in_progress = false;
1842
1843
/*
1844
 * load the shared libraries listed in 'libraries'
1845
 *
1846
 * 'gucname': name of GUC variable, for error reports
1847
 * 'restricted': if true, force libraries to be in $libdir/plugins/
1848
 */
1849
static void
1850
load_libraries(const char *libraries, const char *gucname, bool restricted)
1851
0
{
1852
0
  char     *rawstring;
1853
0
  List     *elemlist;
1854
0
  ListCell   *l;
1855
1856
0
  if (libraries == NULL || libraries[0] == '\0')
1857
0
    return;         /* nothing to do */
1858
1859
  /* Need a modifiable copy of string */
1860
0
  rawstring = pstrdup(libraries);
1861
1862
  /* Parse string into list of filename paths */
1863
0
  if (!SplitDirectoriesString(rawstring, ',', &elemlist))
1864
0
  {
1865
    /* syntax error in list */
1866
0
    list_free_deep(elemlist);
1867
0
    pfree(rawstring);
1868
0
    ereport(LOG,
1869
0
        (errcode(ERRCODE_SYNTAX_ERROR),
1870
0
         errmsg("invalid list syntax in parameter \"%s\"",
1871
0
            gucname)));
1872
0
    return;
1873
0
  }
1874
1875
0
  foreach(l, elemlist)
1876
0
  {
1877
    /* Note that filename was already canonicalized */
1878
0
    char     *filename = (char *) lfirst(l);
1879
0
    char     *expanded = NULL;
1880
1881
    /* If restricting, insert $libdir/plugins if not mentioned already */
1882
0
    if (restricted && first_dir_separator(filename) == NULL)
1883
0
    {
1884
0
      expanded = psprintf("$libdir/plugins/%s", filename);
1885
0
      filename = expanded;
1886
0
    }
1887
0
    load_file(filename, restricted);
1888
0
    ereport(DEBUG1,
1889
0
        (errmsg_internal("loaded library \"%s\"", filename)));
1890
0
    if (expanded)
1891
0
      pfree(expanded);
1892
0
  }
1893
1894
0
  list_free_deep(elemlist);
1895
0
  pfree(rawstring);
1896
0
}
1897
1898
/*
1899
 * process any libraries that should be preloaded at postmaster start
1900
 */
1901
void
1902
process_shared_preload_libraries(void)
1903
0
{
1904
0
  process_shared_preload_libraries_in_progress = true;
1905
0
  load_libraries(shared_preload_libraries_string,
1906
0
           "shared_preload_libraries",
1907
0
           false);
1908
0
  process_shared_preload_libraries_in_progress = false;
1909
0
  process_shared_preload_libraries_done = true;
1910
0
}
1911
1912
/*
1913
 * process any libraries that should be preloaded at backend start
1914
 */
1915
void
1916
process_session_preload_libraries(void)
1917
0
{
1918
0
  load_libraries(session_preload_libraries_string,
1919
0
           "session_preload_libraries",
1920
0
           false);
1921
0
  load_libraries(local_preload_libraries_string,
1922
0
           "local_preload_libraries",
1923
0
           true);
1924
0
}
1925
1926
/*
1927
 * process any shared memory requests from preloaded libraries
1928
 */
1929
void
1930
process_shmem_requests(void)
1931
0
{
1932
0
  process_shmem_requests_in_progress = true;
1933
0
  if (shmem_request_hook)
1934
0
    shmem_request_hook();
1935
0
  process_shmem_requests_in_progress = false;
1936
0
}
1937
1938
void
1939
pg_bindtextdomain(const char *domain)
1940
0
{
1941
#ifdef ENABLE_NLS
1942
  if (my_exec_path[0] != '\0')
1943
  {
1944
    char    locale_path[MAXPGPATH];
1945
1946
    get_locale_path(my_exec_path, locale_path);
1947
    bindtextdomain(domain, locale_path);
1948
    pg_bind_textdomain_codeset(domain);
1949
  }
1950
#endif
1951
0
}