}
/*
- * Other one-time internal sanity checks can go here.
+ * Other one-time internal sanity checks can go here, if they are fast.
+ * (Put any slow processing further down, after postmaster.pid creation.)
*/
if (!CheckDateTokenTables())
{
progname)));
#endif
- /*
- * Initialize SSL library, if specified.
- */
-#ifdef USE_SSL
- if (EnableSSL)
- secure_initialize();
-#endif
-
- /*
- * process any libraries that should be preloaded and optionally
- * pre-initialized
- */
- if (preload_libraries_string)
- process_preload_libraries(preload_libraries_string);
-
/*
* Fork away from controlling terminal, if -S specified.
*
*/
CreateDataDirLockFile(DataDir, true);
+ /*
+ * If timezone is not set, determine what the OS uses. (In theory this
+ * should be done during GUC initialization, but because it can take as
+ * much as several seconds, we delay it until after we've created the
+ * postmaster.pid file. This prevents problems with boot scripts that
+ * expect the pidfile to appear quickly.)
+ */
+ pg_timezone_initialize();
+
+ /*
+ * Initialize SSL library, if specified.
+ */
+#ifdef USE_SSL
+ if (EnableSSL)
+ secure_initialize();
+#endif
+
+ /*
+ * process any libraries that should be preloaded and optionally
+ * pre-initialized
+ */
+ if (preload_libraries_string)
+ process_preload_libraries(preload_libraries_string);
+
/*
* Remove old temporary files. At this point there can be no other
* Postgres processes running in this directory, so this should be
DataDir)));
}
+ /*
+ * Check that the directory belongs to my userid; if not, reject.
+ *
+ * This check is an essential part of the interlock that prevents two
+ * postmasters from starting in the same directory (see CreateLockFile()).
+ * Do not remove or weaken it.
+ *
+ * XXX can we safely enable this check on Windows?
+ */
+#if !defined(WIN32) && !defined(__CYGWIN__)
+ if (stat_buf.st_uid != geteuid())
+ ereport(FATAL,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("data directory \"%s\" has wrong ownership",
+ DataDir),
+ errhint("The server must be started by the user that owns the data directory.")));
+#endif
+
/*
* Check if the directory has group or world access. If so, reject.
*
+ * It would be possible to allow weaker constraints (for example, allow
+ * group access) but we cannot make a general assumption that that is
+ * okay; for example there are platforms where nearly all users customarily
+ * belong to the same group. Perhaps this test should be configurable.
+ *
* XXX temporarily suppress check when on Windows, because there may not
* be proper support for Unix-y file permissions. Need to think of a
* reasonable check to apply on Windows.
strerror(errnum));
/* Set port to non-blocking. Don't do send() if this fails */
- if (!set_noblock(port->sock))
+ if (!pg_set_noblock(port->sock))
return;
send(port->sock, buffer, strlen(buffer) + 1, 0);
*/
static bool xact_started = false;
+/*
+ * Flag to indicate that we are doing the outer loop's read-from-client,
+ * as opposed to any random read from client that might happen within
+ * commands like COPY FROM STDIN.
+ */
+static bool DoingCommandRead = false;
+
/*
* Flags to implement skip-till-Sync-after-error behavior for messages of
* the extended query protocol.
return result;
}
+/*
+ * prepare_for_client_read -- set up to possibly block on client input
+ *
+ * This must be called immediately before any low-level read from the
+ * client connection. It is necessary to do it at a sufficiently low level
+ * that there won't be any other operations except the read kernel call
+ * itself between this call and the subsequent client_read_ended() call.
+ * In particular there mustn't be use of malloc() or other potentially
+ * non-reentrant libc functions. This restriction makes it safe for us
+ * to allow interrupt service routines to execute nontrivial code while
+ * we are waiting for input.
+ */
+void
+prepare_for_client_read(void)
+{
+ if (DoingCommandRead)
+ {
+ /* Enable immediate processing of asynchronous signals */
+ EnableNotifyInterrupt();
+ EnableCatchupInterrupt();
+
+ /* Allow "die" interrupt to be processed while waiting */
+ ImmediateInterruptOK = true;
+
+ /* And don't forget to detect one that already arrived */
+ QueryCancelPending = false;
+ CHECK_FOR_INTERRUPTS();
+ }
+}
+
+/*
+ * client_read_ended -- get out of the client-input state
+ */
+void
+client_read_ended(void)
+{
+ if (DoingCommandRead)
+ {
+ ImmediateInterruptOK = false;
+ QueryCancelPending = false; /* forget any CANCEL signal */
+
+ DisableNotifyInterrupt();
+ DisableCatchupInterrupt();
+ }
+}
+
/*
* Parse a query string and pass it through the rewriter.
if (IsA(parsetree, PrepareStmt))
parsetree = (Node *) (((PrepareStmt *) parsetree)->query);
- if (IsA(parsetree, SelectStmt))
+ if (IsA(parsetree, SelectStmt) &&
+ ((SelectStmt *) parsetree)->into == NULL)
continue; /* optimization for frequent command */
if (log_statement == LOGSTMT_MOD &&
}
commandTag = CreateCommandTag(parsetree);
if (strncmp(commandTag, "CREATE ", strlen("CREATE ")) == 0 ||
+ IsA(parsetree, SelectStmt) || /* SELECT INTO, CREATE AS */
strncmp(commandTag, "ALTER ", strlen("ALTER ")) == 0 ||
strncmp(commandTag, "DROP ", strlen("DROP ")) == 0 ||
IsA(parsetree, GrantStmt) || /* GRANT or REVOKE */
{
if (!SelectConfigFiles(userDoption, argv[0]))
proc_exit(1);
+ /* If timezone is not set, determine what the OS uses */
+ pg_timezone_initialize();
}
/*
* not in other exception-catching places since these interrupts
* are only enabled while we wait for client input.
*/
+ DoingCommandRead = false;
DisableNotifyInterrupt();
DisableCatchupInterrupt();
}
/*
- * (2) deal with pending asynchronous NOTIFY from other backends,
- * and enable async.c's signal handler to execute NOTIFY directly.
- * Then set up other stuff needed before blocking for input.
+ * (2) Allow asynchronous signals to be executed immediately
+ * if they come in while we are waiting for client input.
+ * (This must be conditional since we don't want, say, reads on
+ * behalf of COPY FROM STDIN doing the same thing.)
*/
- QueryCancelPending = false; /* forget any earlier CANCEL
- * signal */
-
- EnableNotifyInterrupt();
- EnableCatchupInterrupt();
-
- /* Allow "die" interrupt to be processed while waiting */
- ImmediateInterruptOK = true;
- /* and don't forget to detect one that already arrived */
- QueryCancelPending = false;
- CHECK_FOR_INTERRUPTS();
+ QueryCancelPending = false; /* forget any earlier CANCEL signal */
+ DoingCommandRead = true;
/*
* (3) read a command (loop blocks here)
/*
* (4) disable async signal conditions again.
*/
- ImmediateInterruptOK = false;
- QueryCancelPending = false; /* forget any CANCEL signal */
-
- DisableNotifyInterrupt();
- DisableCatchupInterrupt();
+ DoingCommandRead = false;
/*
* (5) check for any other interesting events that happened while