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

📄 postmaster.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
			/* Tell pgarch to shut down too; nothing left for it to do */			if (PgArchPID != 0)				kill(PgArchPID, SIGQUIT);			/* Tell pgstat to shut down too; nothing left for it to do */			if (PgStatPID != 0)				kill(PgStatPID, SIGQUIT);			break;		case SIGQUIT:			/*			 * Immediate Shutdown:			 *			 * abort all children with SIGQUIT and exit without attempt to			 * properly shut down data base system.			 */			ereport(LOG,					(errmsg("received immediate shutdown request")));			if (StartupPID != 0)				kill(StartupPID, SIGQUIT);			if (BgWriterPID != 0)				kill(BgWriterPID, SIGQUIT);			if (AutoVacPID != 0)				kill(AutoVacPID, SIGQUIT);			if (PgArchPID != 0)				kill(PgArchPID, SIGQUIT);			if (PgStatPID != 0)				kill(PgStatPID, 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 HAVE_WAITPID	int			status;			/* backend exit status */#else#ifndef WIN32	union wait	status;			/* backend exit status */#endif#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#ifndef WIN32	while ((pid = wait3(&status, WNOHANG, NULL)) > 0)	{		exitstatus = status.w_status;#else	while ((pid = win32_waitpid(&exitstatus)) > 0)	{		/*		 * We need to do this here, and not in CleanupBackend, since this is		 * to be called on all children when we are done with them. Could move		 * to LogChildExit, but that seems like asking for future trouble...		 */		win32_RemoveChild(pid);#endif   /* WIN32 */#endif   /* HAVE_WAITPID */		/*		 * Check if this child was a startup process.		 */		if (StartupPID != 0 && pid == StartupPID)		{			StartupPID = 0;			if (exitstatus != 0)			{				LogChildExit(LOG, _("startup process"),							 pid, exitstatus);				ereport(LOG,				(errmsg("aborting startup due to startup process failure")));				ExitPostmaster(1);			}			/*			 * Startup succeeded - we are done with system startup or			 * recovery.			 */			FatalError = false;			/*			 * Load the flat authorization file into postmaster's cache. The			 * startup process has recomputed this from the database contents,			 * so we wait till it finishes before loading it.			 */			load_role();			/*			 * Crank up the background writer.	It doesn't matter if this			 * fails, we'll just try again later.			 */			Assert(BgWriterPID == 0);			BgWriterPID = StartBackgroundWriter();			/*			 * Go to shutdown mode if a shutdown request was pending.			 * Otherwise, try to start the archiver and stats collector too.			 * (We could, but don't, try to start autovacuum here.)			 */			if (Shutdown > NoShutdown && BgWriterPID != 0)				kill(BgWriterPID, SIGUSR2);			else if (Shutdown == NoShutdown)			{				if (XLogArchivingActive() && PgArchPID == 0)					PgArchPID = pgarch_start();				if (PgStatPID == 0)					PgStatPID = pgstat_start();			}			continue;		}		/*		 * Was it the bgwriter?		 */		if (BgWriterPID != 0 && pid == BgWriterPID)		{			BgWriterPID = 0;			if (exitstatus == 0 && Shutdown > NoShutdown && !FatalError &&				!DLGetHead(BackendList) && AutoVacPID == 0)			{				/*				 * Normal postmaster exit is here: we've seen normal exit of				 * the bgwriter after it's been told to shut down. We expect				 * that it wrote a shutdown checkpoint.  (If for some reason				 * it didn't, recovery will occur on next postmaster start.)				 *				 * Note: we do not wait around for exit of the archiver or				 * stats processes.  They've been sent SIGQUIT by this point,				 * and in any case contain logic to commit hara-kiri if they				 * notice the postmaster is gone.				 */				ExitPostmaster(0);			}			/*			 * Any unexpected exit of the bgwriter is treated as a crash.			 */			HandleChildCrash(pid, exitstatus,							 _("background writer process"));			continue;		}		/*		 * Was it the autovacuum process?  Normal exit can be ignored; we'll		 * start a new one at the next iteration of the postmaster's main		 * loop, if necessary.		 *		 * An unexpected exit must crash the system.		 */		if (AutoVacPID != 0 && pid == AutoVacPID)		{			AutoVacPID = 0;			autovac_stopped();			/* Tell the collector about process termination */			pgstat_beterm(pid);			if (exitstatus != 0)				HandleChildCrash(pid, exitstatus,								 _("autovacuum process"));			continue;		}		/*		 * Was it the archiver?  If so, just try to start a new one; no need		 * to force reset of the rest of the system.  (If fail, we'll try		 * again in future cycles of the main loop.)		 */		if (PgArchPID != 0 && pid == PgArchPID)		{			PgArchPID = 0;			if (exitstatus != 0)				LogChildExit(LOG, _("archiver process"),							 pid, exitstatus);			if (XLogArchivingActive() &&				StartupPID == 0 && !FatalError && Shutdown == NoShutdown)				PgArchPID = pgarch_start();			continue;		}		/*		 * Was it the statistics collector?  If so, just try to start a new		 * one; no need to force reset of the rest of the system.  (If fail,		 * we'll try again in future cycles of the main loop.)		 */		if (PgStatPID != 0 && pid == PgStatPID)		{			PgStatPID = 0;			if (exitstatus != 0)				LogChildExit(LOG, _("statistics collector process"),							 pid, exitstatus);			if (StartupPID == 0 && !FatalError && Shutdown == NoShutdown)				PgStatPID = pgstat_start();			continue;		}		/* Was it the system logger? try to start a new one */		if (SysLoggerPID != 0 && pid == SysLoggerPID)		{			SysLoggerPID = 0;			/* for safety's sake, launch new logger *first* */			SysLoggerPID = SysLogger_Start();			if (exitstatus != 0)				LogChildExit(LOG, _("system logger process"),							 pid, exitstatus);			continue;		}		/*		 * Else do standard backend child cleanup.		 */		CleanupBackend(pid, exitstatus);	}							/* loop over pending child-death reports */	if (FatalError)	{		/*		 * Wait for all important children to exit, then reset shmem and		 * StartupDataBase.  (We can ignore the archiver and stats processes		 * here since they are not connected to shmem.)		 */		if (DLGetHead(BackendList) || StartupPID != 0 || BgWriterPID != 0 ||			AutoVacPID != 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) || StartupPID != 0 || AutoVacPID != 0)			goto reaper_done;		/* Start the bgwriter if not running */		if (BgWriterPID == 0)			BgWriterPID = StartBackgroundWriter();		/* And tell it to shut down */		if (BgWriterPID != 0)			kill(BgWriterPID, SIGUSR2);		/* Tell pgarch to shut down too; nothing left for it to do */		if (PgArchPID != 0)			kill(PgArchPID, SIGQUIT);		/* Tell pgstat to shut down too; nothing left for it to do */		if (PgStatPID != 0)			kill(PgStatPID, SIGQUIT);	}reaper_done:	PG_SETMASK(&UnBlockSig);	errno = save_errno;}/* * CleanupBackend -- cleanup after terminated backend. * * Remove all local state associated with backend. */static voidCleanupBackend(int pid,			   int exitstatus)	/* child's exit status. */{	Dlelem	   *curr;	LogChildExit(DEBUG2, _("server 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)	{		HandleChildCrash(pid, exitstatus, _("server process"));		return;	}	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))	{		Backend    *bp = (Backend *) DLE_VAL(curr);		if (bp->pid == pid)		{			DLRemove(curr);			free(bp);			DLFreeElem(curr);#ifdef EXEC_BACKEND			ShmemBackendArrayRemove(pid);#endif			/* Tell the collector about backend termination */			pgstat_beterm(pid);			break;		}	}}/* * HandleChildCrash -- cleanup after failed backend, bgwriter, or autovacuum. * * The objectives here are to clean up our local state about the child * process, and to signal all other remaining children to quickdie. */static voidHandleChildCrash(int pid, int exitstatus, const char *procname){	Dlelem	   *curr,			   *next;	Backend    *bp;	/*	 * Make log entry unless there was a previous crash (if so, nonzero exit	 * status is to be expected in SIGQUIT response; don't clutter log)	 */	if (!FatalError)	{		LogChildExit(LOG, procname, pid, exitstatus);		ereport(LOG,				(errmsg("terminating any other active server processes")));	}	/* Process regular backends */	for (curr = DLGetHead(BackendList); curr; curr = next)	{		next = DLGetSucc(curr);		bp = (Backend *) DLE_VAL(curr);		if (bp->pid == pid)		{			/*			 * Found entry for freshly-dead backend, so remove it.			 */			DLRemove(curr);			free(bp);			DLFreeElem(curr);#ifdef EXEC_BACKEND			ShmemBackendArrayRemove(pid);#endif			/* Tell the collector about backend termination */			pgstat_beterm(pid);			/* Keep looping so we can signal remaining backends */		}		else		{			/*			 * 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));			}		}	}	/* Take care of the bgwriter too */	if (pid == BgWriterPID)		BgWriterPID = 0;	else if (BgWriterPID != 0 && !FatalError)	{		ereport(DEBUG2,				(errmsg_internal("sending %s to process %d",								 (SendStop ? "SIGSTOP" : "SIGQUIT"),								 (int) BgWriterPID)));		kill(BgWriterPID, (SendStop ? SIGSTOP : SIGQUIT));	}	/* Take care of the autovacuum daemon too */	if (pid == AutoVacPID)		AutoVacPID = 0;	else if (AutoVacPID != 0 && !FatalError)	{		ereport(DEBUG2,				(errmsg_internal("sending %s to process %d",								 (SendStop ? "SIGSTOP" : "SIGQUIT"),								 (int) AutoVacPID)));		kill(AutoVacPID, (SendStop ? SIGSTOP : SIGQUIT));	}	/* Force a power-cycle of the pgarch process too */	/* (Shouldn't be necessary, but just for luck) */	if (PgArchPID != 0 && !FatalError)	{		ereport(DEBUG2,				(errmsg_internal("sending %s to process %d",								 "SIGQUIT",								 (int) PgArchPID)));		kill(PgArchPID, SIGQUIT);	}	/* Force a power-cycle of the pgstat processes too */	/* (Shouldn't be necessary, but just for luck) */	if (PgStatPID != 0 && !FatalError)	{		ereport(DEBUG2,				(errmsg_internal("sending %s to process %d",								 "SIGQUIT",								 (int) PgStatPID)));		kill(PgStatPID, SIGQUIT);	}	/* We do NOT restart the syslogger */	FatalError = true;}/* * Log the death of a child process. */static voidLogChildExit(int lev, const char *procname, int pid, int exitstatus){	if (WIFEXITED(exitstatus))		ereport(lev,		/*		 * translator: %s is a noun phrase describing a child process, such as		 * "server process"		 */				(errmsg("%s (PID %d) exited with exit code %d",						procname, pid, WEXITSTATUS(exitstatus))));	else if (WIFSIGNALED(exitstatus))		ereport(lev,		/*		 * translator: %s is a noun phrase describing a child process, such as		 * "server process"		 */				(errmsg("%s (PID %d) was terminated by signal %d",						procname, pid, WTERMSIG(exitstatus))));	else		ereport(lev,		/*		 * translator: %s is a noun phrase describing a child process, such as		 * "server process"		 */				(errmsg("%s (PID %d) exited with unexpected status %d",						procname, pid, exitstatus)));}/* * Send a signal to all backend children (but NOT special children) */static voidSignalChildren(int signal){	Dlelem	   *curr;	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(cu

⌨️ 快捷键说明

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