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

📄 postmaster.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
		return CAC_SHUTDOWN;	if (StartupPID)		return CAC_STARTUP;	if (FatalError)		return CAC_RECOVERY;	/*	 * Don't start too many children.	 *	 * We allow more connections than we can have backends here because some	 * might still be authenticating; they might fail auth, or some	 * existing backend might exit before the auth cycle is completed. The	 * exact MaxBackends limit is enforced when a new backend tries to	 * join the shared-inval backend array.	 */	if (CountChildren() >= 2 * MaxBackends)		return CAC_TOOMANY;	return CAC_OK;}/* * ConnCreate -- create a local connection data structure */static Port *ConnCreate(int serverFd){	Port	   *port;	if (!(port = (Port *) calloc(1, sizeof(Port))))	{		ereport(LOG,				(errcode(ERRCODE_OUT_OF_MEMORY),				 errmsg("out of memory")));		ExitPostmaster(1);	}	if (StreamConnection(serverFd, port) != STATUS_OK)	{		StreamClose(port->sock);		ConnFree(port);		port = NULL;	}	else	{		/*		 * Precompute password salt values to use for this connection.		 * It's slightly annoying to do this long in advance of knowing		 * whether we'll need 'em or not, but we must do the random()		 * calls before we fork, not after.  Else the postmaster's random		 * sequence won't get advanced, and all backends would end up		 * using the same salt...		 */		RandomSalt(port->cryptSalt, port->md5Salt);	}	return port;}/* * ConnFree -- free a local connection data structure */static voidConnFree(Port *conn){#ifdef USE_SSL	secure_close(conn);#endif	free(conn);}/* * ClosePostmasterPorts -- close all the postmaster's open sockets * * This is called during child process startup to release file descriptors * that are not needed by that child process.  The postmaster still has * them open, of course. */voidClosePostmasterPorts(bool pgstat_too){	int			i;	/* Close the listen sockets */	for (i = 0; i < MAXLISTEN; i++)	{		if (ListenSocket[i] != -1)		{			StreamClose(ListenSocket[i]);			ListenSocket[i] = -1;		}	}	/* Close pgstat control sockets, unless we're starting pgstat itself */	if (pgstat_too)		pgstat_close_sockets();}/* * reset_shared -- reset shared memory and semaphores */static voidreset_shared(unsigned short port){	/*	 * Create or re-create shared memory and semaphores.	 *	 * Note: in each "cycle of life" we will normally assign the same IPC	 * keys (if using SysV shmem and/or semas), since the port number is	 * used to determine IPC keys.	This helps ensure that we will clean	 * up dead IPC objects if the postmaster crashes and is restarted.	 */	CreateSharedMemoryAndSemaphores(false, MaxBackends, port);}/* * SIGHUP -- reread config files, and tell children to do same */static voidSIGHUP_handler(SIGNAL_ARGS){	int			save_errno = errno;	PG_SETMASK(&BlockSig);	if (Shutdown <= SmartShutdown)	{		ereport(LOG,			 (errmsg("received SIGHUP, reloading configuration files")));		ProcessConfigFile(PGC_SIGHUP);#ifdef EXEC_BACKEND		write_nondefault_variables(PGC_SIGHUP);#endif		SignalChildren(SIGHUP);		load_hba();		load_ident();	}	PG_SETMASK(&UnBlockSig);	errno = save_errno;}/* * pmdie -- signal handler for processing various postmaster signals. */static voidpmdie(SIGNAL_ARGS){	int			save_errno = errno;	PG_SETMASK(&BlockSig);	ereport(DEBUG2,			(errmsg_internal("postmaster received signal %d",							 postgres_signal_arg)));	switch (postgres_signal_arg)	{		case SIGTERM:			/*			 * Smart Shutdown:			 *			 * Wait for children to end their work and ShutdownDataBase.			 */			if (Shutdown >= SmartShutdown)				break;			Shutdown = SmartShutdown;			ereport(LOG,					(errmsg("received smart shutdown request")));			if (DLGetHead(BackendList)) /* let reaper() handle this */				break;			/*			 * No children left. Shutdown data base system.			 */			if (StartupPID > 0 || FatalError)	/* let reaper() handle												 * this */				break;			if (ShutdownPID > 0)			{				elog(PANIC, "shutdown process %d already running",					 (int) ShutdownPID);				abort();			}			ShutdownPID = ShutdownDataBase();			break;		case SIGINT:			/*			 * Fast Shutdown:			 *			 * abort all children with SIGTERM (rollback active transactions			 * and exit) and ShutdownDataBase when they are gone.			 */			if (Shutdown >= FastShutdown)				break;			ereport(LOG,					(errmsg("received fast shutdown request")));			if (DLGetHead(BackendList)) /* let reaper() handle this */			{				Shutdown = FastShutdown;				if (!FatalError)				{					ereport(LOG,							(errmsg("aborting any active transactions")));					SignalChildren(SIGTERM);				}				break;			}			if (Shutdown > NoShutdown)			{				Shutdown = FastShutdown;				break;			}			Shutdown = FastShutdown;			/*			 * No children left. Shutdown data base system.			 */			if (StartupPID > 0 || FatalError)	/* let reaper() handle												 * this */				break;			if (ShutdownPID > 0)			{				elog(PANIC, "shutdown process %d already running",					 (int) ShutdownPID);				abort();			}			ShutdownPID = ShutdownDataBase();			break;		case SIGQUIT:			/*			 * Immediate Shutdown:			 *			 * abort all children with SIGQUIT and exit without attempt to			 * properly shutdown data base system.			 */			ereport(LOG,					(errmsg("received immediate shutdown request")));			if (ShutdownPID > 0)				kill(ShutdownPID, SIGQUIT);			if (StartupPID > 0)				kill(StartupPID, SIGQUIT);			if (DLGetHead(BackendList))				SignalChildren(SIGQUIT);			ExitPostmaster(0);			break;	}	PG_SETMASK(&UnBlockSig);	errno = save_errno;}/* * Reaper -- signal handler to cleanup after a backend (child) dies. */static voidreaper(SIGNAL_ARGS){	int			save_errno = errno;#ifdef WIN32#warning fix waidpid for Win32#else#ifdef HAVE_WAITPID	int			status;			/* backend exit status */#else	union wait	status;			/* backend exit status */#endif	int			exitstatus;	int			pid;			/* process id of dead backend */	PG_SETMASK(&BlockSig);	ereport(DEBUG4,			(errmsg_internal("reaping dead processes")));#ifdef HAVE_WAITPID	while ((pid = waitpid(-1, &status, WNOHANG)) > 0)	{		exitstatus = status;#else	while ((pid = wait3(&status, WNOHANG, NULL)) > 0)	{		exitstatus = status.w_status;#endif		/*		 * Check if this child was the statistics collector. If so, try to		 * start a new one.  (If fail, we'll try again in future cycles of		 * the main loop.)		 */		if (pgstat_ispgstat(pid))		{			LogChildExit(LOG, gettext("statistics collector process"),						 pid, exitstatus);			pgstat_start();			continue;		}		/*		 * Check if this child was a shutdown or startup process.		 */		if (ShutdownPID > 0 && pid == ShutdownPID)		{			if (exitstatus != 0)			{				LogChildExit(LOG, gettext("shutdown process"),							 pid, exitstatus);				ExitPostmaster(1);			}			/* Normal postmaster exit is here */			ExitPostmaster(0);		}		if (StartupPID > 0 && pid == StartupPID)		{			if (exitstatus != 0)			{				LogChildExit(LOG, gettext("startup process"),							 pid, exitstatus);				ereport(LOG,						(errmsg("aborting startup due to startup process failure")));				ExitPostmaster(1);			}			StartupPID = 0;			/*			 * Startup succeeded - remember its ID and RedoRecPtr.			 *			 * NB: this MUST happen before we fork a checkpoint or shutdown			 * subprocess, else they will have wrong local ThisStartUpId.			 */			SetThisStartUpID();			FatalError = false; /* done with recovery */			/*			 * Arrange for first checkpoint to occur after standard delay.			 */			CheckPointPID = 0;			checkpointed = time(NULL);			/*			 * Go to shutdown mode if a shutdown request was pending.			 */			if (Shutdown > NoShutdown)			{				if (ShutdownPID > 0)				{					elog(PANIC, "startup process %d died while shutdown process %d already running",						 pid, (int) ShutdownPID);					abort();				}				ShutdownPID = ShutdownDataBase();			}			goto reaper_done;		}		/*		 * Else do standard child cleanup.		 */		CleanupProc(pid, exitstatus);	}							/* loop over pending child-death reports */#endif	if (FatalError)	{		/*		 * Wait for all children exit, then reset shmem and		 * StartupDataBase.		 */		if (DLGetHead(BackendList) || StartupPID > 0 || ShutdownPID > 0)			goto reaper_done;		ereport(LOG,			(errmsg("all server processes terminated; reinitializing")));		shmem_exit(0);		reset_shared(PostPortNumber);		StartupPID = StartupDataBase();		goto reaper_done;	}	if (Shutdown > NoShutdown)	{		if (DLGetHead(BackendList))			goto reaper_done;		if (StartupPID > 0 || ShutdownPID > 0)			goto reaper_done;		ShutdownPID = ShutdownDataBase();	}reaper_done:	PG_SETMASK(&UnBlockSig);	errno = save_errno;}/* * CleanupProc -- cleanup after terminated backend. * * Remove all local state associated with backend. */static voidCleanupProc(int pid,			int exitstatus)		/* child's exit status. */{	Dlelem	   *curr,			   *next;	Backend    *bp;	LogChildExit(DEBUG2, gettext("child process"), pid, exitstatus);	/*	 * If a backend dies in an ugly way (i.e. exit status not 0) then we	 * must signal all other backends to quickdie.	If exit status is zero	 * we assume everything is hunky dory and simply remove the backend	 * from the active backend list.	 */	if (exitstatus == 0)	{		curr = DLGetHead(BackendList);		while (curr)		{			bp = (Backend *) DLE_VAL(curr);			if (bp->pid == pid)			{				DLRemove(curr);				free(bp);				DLFreeElem(curr);				break;			}			curr = DLGetSucc(curr);		}		if (pid == CheckPointPID)		{			CheckPointPID = 0;			if (!FatalError)			{				checkpointed = time(NULL);				/* Update RedoRecPtr for future child backends */				GetSavedRedoRecPtr();			}		}		else			pgstat_beterm(pid);		return;	}	/* below here we're dealing with a non-normal exit */	/* Make log entry unless we did so already */	if (!FatalError)	{		LogChildExit(LOG,				 (pid == CheckPointPID) ? gettext("checkpoint process") :					 gettext("server process"),					 pid, exitstatus);		ereport(LOG,			  (errmsg("terminating any other active server processes")));	}	curr = DLGetHead(BackendList);	while (curr)	{		next = DLGetSucc(curr);		bp = (Backend *) DLE_VAL(curr);		if (bp->pid != pid)		{			/*			 * This backend is still alive.  Unless we did so already,			 * tell it to commit hara-kiri.			 *			 * SIGQUIT is the special signal that says exit without proc_exit			 * and let the user know what's going on. But if SendStop is			 * set (-s on command line), then we send SIGSTOP instead, so			 * that we can get core dumps from all backends by hand.			 */			if (!FatalError)			{				ereport(DEBUG2,						(errmsg_internal("sending %s to process %d",										 (SendStop ? "SIGSTOP" : "SIGQUIT"),										 (int) bp->pid)));				kill(bp->pid, (SendStop ? SIGSTOP : SIGQUIT));			}		}		else

⌨️ 快捷键说明

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