⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 postmaster.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * postmaster.c *	  This program acts as a clearing house for requests to the *	  POSTGRES system.	Frontend programs send a startup message *	  to the Postmaster and the postmaster uses the info in the *	  message to setup a backend process. * *	  The postmaster also manages system-wide operations such as *	  startup, shutdown, and periodic checkpoints.	The postmaster *	  itself doesn't do those operations, mind you --- it just forks *	  off a subprocess to do them at the right times.  It also takes *	  care of resetting the system if a backend crashes. * *	  The postmaster process creates the shared memory and semaphore *	  pools during startup, but as a rule does not touch them itself. *	  In particular, it is not a member of the PGPROC array of backends *	  and so it cannot participate in lock-manager operations.	Keeping *	  the postmaster away from shared memory operations makes it simpler *	  and more reliable.  The postmaster is almost always able to recover *	  from crashes of individual backends by resetting shared memory; *	  if it did much with shared memory then it would be prone to crashing *	  along with the backends. * *	  When a request message is received, we now fork() immediately. *	  The child process performs authentication of the request, and *	  then becomes a backend if successful.  This allows the auth code *	  to be written in a simple single-threaded style (as opposed to the *	  crufty "poor man's multitasking" code that used to be needed). *	  More importantly, it ensures that blockages in non-multithreaded *	  libraries like SSL or PAM cannot cause denial of service to other *	  clients. * * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.347.2.2 2004/02/23 20:46:16 tgl Exp $ * * NOTES * * Initialization: *		The Postmaster sets up a few shared memory data structures *		for the backends.  It should at the very least initialize the *		lock manager. * * Synchronization: *		The Postmaster shares memory with the backends but should avoid *		touching shared memory, so as not to become stuck if a crashing *		backend screws up locks or shared memory.  Likewise, the Postmaster *		should never block on messages from frontend clients. * * Garbage Collection: *		The Postmaster cleans up after backends if they have an emergency *		exit and/or core dump. * *------------------------------------------------------------------------- */#include "postgres.h"#include <unistd.h>#include <signal.h>#include <sys/wait.h>#include <ctype.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/socket.h>#include <errno.h>#include <fcntl.h>#include <time.h>#include <sys/param.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <limits.h>#ifdef HAVE_SYS_SELECT_H#include <sys/select.h>#endif#ifdef HAVE_GETOPT_H#include <getopt.h>#endif#ifdef USE_RENDEZVOUS#include <DNSServiceDiscovery/DNSServiceDiscovery.h>#endif#include "catalog/pg_database.h"#include "commands/async.h"#include "lib/dllist.h"#include "libpq/auth.h"#include "libpq/crypt.h"#include "libpq/libpq.h"#include "libpq/pqcomm.h"#include "libpq/pqsignal.h"#include "miscadmin.h"#include "nodes/nodes.h"#include "storage/fd.h"#include "storage/ipc.h"#include "storage/pg_shmem.h"#include "storage/pmsignal.h"#include "storage/proc.h"#include "access/xlog.h"#include "tcop/tcopprot.h"#include "utils/guc.h"#include "utils/memutils.h"#include "utils/ps_status.h"#include "bootstrap/bootstrap.h"#include "pgstat.h"#define INVALID_SOCK	(-1)#ifdef HAVE_SIGPROCMASKsigset_t	UnBlockSig,			BlockSig,			AuthBlockSig;#elseint			UnBlockSig,			BlockSig,			AuthBlockSig;#endif/* * List of active backends (or child processes anyway; we don't actually * know whether a given child has become a backend or is still in the * authorization phase).  This is used mainly to keep track of how many * children we have and send them appropriate signals when necessary. */typedef struct bkend{	pid_t		pid;			/* process id of backend */	long		cancel_key;		/* cancel key for cancels for this backend */} Backend;static Dllist *BackendList;/* The socket number we are listening for connections on */int			PostPortNumber;char	   *UnixSocketDir;char	   *VirtualHost;/* * MaxBackends is the limit on the number of backends we can start. * Note that a larger MaxBackends value will increase the size of the * shared memory area as well as cause the postmaster to grab more * kernel semaphores, even if you never actually use that many * backends. */int			MaxBackends;/* * ReservedBackends is the number of backends reserved for superuser use. * This number is taken out of the pool size given by MaxBackends so * number of backend slots available to non-superusers is * (MaxBackends - ReservedBackends).  Note what this really means is * "if there are <= ReservedBackends connections available, only superusers * can make new connections" --- pre-existing superuser connections don't * count against the limit. */int			ReservedBackends;static char *progname = (char *) NULL;/* The socket(s) we're listening to. */#define MAXLISTEN	10static int	ListenSocket[MAXLISTEN];/* Used to reduce macros tests */#ifdef EXEC_BACKENDconst bool	ExecBackend = true;#elseconst bool	ExecBackend = false;#endif/* * Set by the -o option */static char ExtraOptions[MAXPGPATH];/* * These globals control the behavior of the postmaster in case some * backend dumps core.	Normally, it kills all peers of the dead backend * and reinitializes shared memory.  By specifying -s or -n, we can have * the postmaster stop (rather than kill) peers and not reinitialize * shared data structures. */static bool Reinit = true;static int	SendStop = false;/* still more option variables */bool		NetServer = false;	/* listen on TCP/IP */bool		EnableSSL = false;bool		SilentMode = false; /* silent mode (-S) */int			PreAuthDelay = 0;int			AuthenticationTimeout = 60;int			CheckPointTimeout = 300;int			CheckPointWarning = 30;time_t		LastSignalledCheckpoint = 0;bool		log_hostname;		/* for ps display */bool		LogSourcePort;bool		Log_connections = false;bool		Db_user_namespace = false;char	   *rendezvous_name;/* For FNCTL_NONBLOCK */#if defined(WIN32) || defined(__BEOS__)long		ioctlsocket_ret = 1;#endif/* list of library:init-function to be preloaded */char	   *preload_libraries_string = NULL;/* Startup/shutdown state */static pid_t StartupPID = 0,			ShutdownPID = 0,			CheckPointPID = 0;static time_t checkpointed = 0;#define			NoShutdown		0#define			SmartShutdown	1#define			FastShutdown	2static int	Shutdown = NoShutdown;static bool FatalError = false; /* T if recovering from backend crash */bool		ClientAuthInProgress = false;		/* T during new-client												 * authentication *//* * State for assigning random salts and cancel keys. * Also, the global MyCancelKey passes the cancel key assigned to a given * backend from the postmaster to that backend (via fork). */static unsigned int random_seed = 0;static int	debug_flag = 0;extern char *optarg;extern int	optind,			opterr;#ifdef HAVE_INT_OPTRESETextern int	optreset;#endif/* * postmaster.c - function prototypes */static void pmdaemonize(int argc, char *argv[]);static Port *ConnCreate(int serverFd);static void ConnFree(Port *port);static void reset_shared(unsigned short port);static void SIGHUP_handler(SIGNAL_ARGS);static void pmdie(SIGNAL_ARGS);static void reaper(SIGNAL_ARGS);static void sigusr1_handler(SIGNAL_ARGS);static void dummy_handler(SIGNAL_ARGS);static void CleanupProc(int pid, int exitstatus);static void LogChildExit(int lev, const char *procname,			 int pid, int exitstatus);static int	BackendFork(Port *port);static void ExitPostmaster(int status);static void usage(const char *);static int	ServerLoop(void);static int	BackendStartup(Port *port);static int	ProcessStartupPacket(Port *port, bool SSLdone);static void processCancelRequest(Port *port, void *pkt);static int	initMasks(fd_set *rmask);static void report_fork_failure_to_client(Port *port, int errnum);enum CAC_state{	CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY};static enum CAC_state canAcceptConnections(void);static long PostmasterRandom(void);static void RandomSalt(char *cryptSalt, char *md5Salt);static void SignalChildren(int signal);static int	CountChildren(void);static bool CreateOptsFile(int argc, char *argv[]);static pid_t SSDataBase(int xlop);static voidpostmaster_error(const char *fmt,...)/* This lets gcc check the format string for consistency. */__attribute__((format(printf, 1, 2)));#define StartupDataBase()		SSDataBase(BS_XLOG_STARTUP)#define CheckPointDataBase()	SSDataBase(BS_XLOG_CHECKPOINT)#define ShutdownDataBase()		SSDataBase(BS_XLOG_SHUTDOWN)static voidcheckDataDir(const char *checkdir){	char		path[MAXPGPATH];	FILE	   *fp;	struct stat stat_buf;	if (checkdir == NULL)	{		fprintf(stderr,				gettext("%s does not know where to find the database system data.\n"						"You must specify the directory that contains the database system\n"						"either by specifying the -D invocation option or by setting the\n"						"PGDATA environment variable.\n"),				progname);		ExitPostmaster(2);	}	if (stat(checkdir, &stat_buf) == -1)	{		if (errno == ENOENT)			ereport(FATAL,					(errcode_for_file_access(),					 errmsg("data directory \"%s\" does not exist",							checkdir)));		else			ereport(FATAL,					(errcode_for_file_access(),			 errmsg("could not read permissions of directory \"%s\": %m",					checkdir)));	}	/*	 * Check if the directory has group or world access.  If so, reject.	 *	 * 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.	 */#if !defined(__CYGWIN__) && !defined(WIN32)	if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))		ereport(FATAL,				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),				 errmsg("data directory \"%s\" has group or world access",						checkdir),				 errdetail("Permissions should be u=rwx (0700).")));#endif	/* Look for PG_VERSION before looking for pg_control */	ValidatePgVersion(checkdir);	snprintf(path, sizeof(path), "%s/global/pg_control", checkdir);	fp = AllocateFile(path, PG_BINARY_R);	if (fp == NULL)	{		fprintf(stderr,				gettext("%s: could not find the database system\n"						"Expected to find it in the directory \"%s\",\n"						"but could not open file \"%s\": %s\n"),				progname, checkdir, path, strerror(errno));		ExitPostmaster(2);	}	FreeFile(fp);}#ifdef USE_RENDEZVOUS/* reg_reply -- empty callback function for DNSServiceRegistrationCreate() */static voidreg_reply(DNSServiceRegistrationReplyErrorType errorCode, void *context){}#endifintPostmasterMain(int argc, char *argv[]){	int			opt;	int			status;	char		original_extraoptions[MAXPGPATH];	char	   *potential_DataDir = NULL;	int			i;	*original_extraoptions = '\0';	progname = argv[0];	IsPostmasterEnvironment = true;	/*	 * Catch standard options before doing much else.  This even works on	 * systems without getopt_long.	 */	if (argc > 1)	{		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)		{			usage(progname);			ExitPostmaster(0);		}		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)		{			puts("postmaster (PostgreSQL) " PG_VERSION);			ExitPostmaster(0);		}	}	/*	 * for security, no dir or file created can be group or other	 * accessible	 */	umask((mode_t) 0077);	MyProcPid = getpid();	/*	 * Fire up essential subsystems: memory management	 */	MemoryContextInit();	/*	 * By default, palloc() requests in the postmaster will be allocated	 * in the PostmasterContext, which is space that can be recycled by	 * backends.  Allocated data that needs to be available to backends	 * should be allocated in TopMemoryContext.	 */	PostmasterContext = AllocSetContextCreate(TopMemoryContext,											  "Postmaster",											  ALLOCSET_DEFAULT_MINSIZE,											  ALLOCSET_DEFAULT_INITSIZE,											  ALLOCSET_DEFAULT_MAXSIZE);	MemoryContextSwitchTo(PostmasterContext);	IgnoreSystemIndexes(false);	/*	 * Options setup	 */	InitializeGUCOptions();	potential_DataDir = getenv("PGDATA");		/* default value */	opterr = 1;	while ((opt = getopt(argc, argv, "A:a:B:b:c:D:d:Fh:ik:lm:MN:no:p:Ss-:")) != -1)	{		switch (opt)		{			case 'A':#ifdef USE_ASSERT_CHECKING				SetConfigOption("debug_assertions", optarg, PGC_POSTMASTER, PGC_S_ARGV);#else				postmaster_error("assert checking is not compiled in");#endif				break;			case 'a':				/* Can no longer set authentication method. */				break;			case 'B':				SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);				break;			case 'b':				/* Can no longer set the backend executable file to use. */				break;			case 'D':				potential_DataDir = optarg;				break;			case 'd':				{					/* Turn on debugging for the postmaster. */					char	   *debugstr = palloc(strlen("debug") + strlen(optarg) + 1);					sprintf(debugstr, "debug%s", optarg);					SetConfigOption("log_min_messages", debugstr,									PGC_POSTMASTER, PGC_S_ARGV);					pfree(debugstr);					debug_flag = atoi(optarg);					break;				}			case 'F':				SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV);				break;			case 'h':				SetConfigOption("virtual_host", optarg, PGC_POSTMASTER, PGC_S_ARGV);				break;			case 'i':				SetConfigOption("tcpip_socket", "true", PGC_POSTMASTER, PGC_S_ARGV);				break;			case 'k':				SetConfigOption("unix_socket_directory", optarg, PGC_POSTMASTER, PGC_S_ARGV);				break;#ifdef USE_SSL			case 'l':				SetConfigOption("ssl", "true", PGC_POSTMASTER, PGC_S_ARGV);				break;#endif			case 'm':				/* Multiplexed backends no longer supported. */				break;			case 'M':				/*				 * ignore this flag.  This may be passed in because the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -