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