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

📄 postmaster.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
			int exitstatus)		/* child's exit status. */{	Dlelem	   *prev,			   *curr;	Backend    *bp;	int			sig;	if (DebugLvl)	{		fprintf(stderr, "%s: CleanupProc: pid %d exited with status %d\n",				progname, 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)	{		curr = DLGetHead(BackendList);		while (curr)		{			bp = (Backend *) DLE_VAL(curr);			if (bp->pid == pid)			{				DLRemove(curr);				free(bp);				DLFreeElem(curr);				break;			}			curr = DLGetSucc(curr);		}		ProcRemove(pid);		return;	}	curr = DLGetHead(BackendList);	while (curr)	{		bp = (Backend *) DLE_VAL(curr);		/* -----------------		 * SIGUSR1 is the special signal that says exit		 * without proc_exit and let the user know what's going on.		 * ProcSemaphoreKill() cleans up the backends semaphore.  If		 * SendStop is set (-s on command line), then we send a SIGSTOP so		 * that we can core dumps from all backends by hand.		 * -----------------		 */		sig = (SendStop) ? SIGSTOP : SIGUSR1;		if (bp->pid != pid)		{			if (DebugLvl)				fprintf(stderr, "%s: CleanupProc: sending %s to process %d\n",						progname,						(sig == SIGUSR1)						? "SIGUSR1" : "SIGSTOP",						bp->pid);			kill(bp->pid, sig);		}		ProcRemove(bp->pid);		prev = DLGetPred(curr);		DLRemove(curr);		free(bp);		DLFreeElem(curr);		if (!prev)		{						/* removed head */			curr = DLGetHead(BackendList);			continue;		}		curr = DLGetSucc(prev);	}	/*	 * Nothing up my sleeve here, ActiveBackends means that since the last	 * time we recreated shared memory and sems another frontend has	 * requested and received a connection and I have forked off another	 * backend.  This prevents me from reinitializing shared stuff more	 * than once for the set of backends that caused the failure and were	 * killed off.	 */	if (ActiveBackends == TRUE && Reinit)	{		if (DebugLvl)			fprintf(stderr, "%s: CleanupProc: reinitializing shared memory and semaphores\n",					progname);		shmem_exit(0);		reset_shared(PostPortName);	}}/* * Send a signal to all chidren processes. */static voidSignalChildren(int signal){	Dlelem	   *curr,			   *next;	Backend    *bp;	int			mypid = getpid();	curr = DLGetHead(BackendList);	while (curr)	{		next = DLGetSucc(curr);		bp = (Backend *) DLE_VAL(curr);		if (bp->pid != mypid)		{			TPRINTF(TRACE_VERBOSE,					"SignalChildren: sending signal %d to process %d",					signal, bp->pid);			kill(bp->pid, signal);		}		curr = next;	}}/* * BackendStartup -- start backend process * * returns: STATUS_ERROR if the fork/exec failed, STATUS_OK *		otherwise. * */static intBackendStartup(Port *port){	Backend    *bn;				/* for backend cleanup */	int			pid,				i;#ifdef CYR_RECODE#define NR_ENVIRONMENT_VBL 6	char		ChTable[80];#else#define NR_ENVIRONMENT_VBL 5#endif	static char envEntry[NR_ENVIRONMENT_VBL][2 * ARGV_SIZE];	for (i = 0; i < NR_ENVIRONMENT_VBL; ++i)		MemSet(envEntry[i], 0, 2 * ARGV_SIZE);	/*	 * Set up the necessary environment variables for the backend This	 * should really be some sort of message....	 */	sprintf(envEntry[0], "POSTPORT=%d", PostPortName);	putenv(envEntry[0]);	sprintf(envEntry[1], "POSTID=%d", NextBackendTag);	putenv(envEntry[1]);	sprintf(envEntry[2], "PG_USER=%s", port->user);	putenv(envEntry[2]);	if (!getenv("PGDATA"))	{		sprintf(envEntry[3], "PGDATA=%s", DataDir);		putenv(envEntry[3]);	}	sprintf(envEntry[4], "IPC_KEY=%d", ipc_key);	putenv(envEntry[4]);#ifdef CYR_RECODE	GetCharSetByHost(ChTable, port->raddr.in.sin_addr.s_addr, DataDir);	if (*ChTable != '\0')	{		sprintf(envEntry[5], "PG_RECODETABLE=%s", ChTable);		putenv(envEntry[5]);	}#endif	/*	 * Compute the cancel key that will be assigned to this backend. The	 * backend will have its own copy in the forked-off process' value of	 * MyCancelKey, so that it can transmit the key to the frontend.	 */	MyCancelKey = PostmasterRandom();	if (DebugLvl > 2)	{		char	  **p;		extern char **environ;		fprintf(stderr, "%s: BackendStartup: environ dump:\n",				progname);		fprintf(stderr, "-----------------------------------------\n");		for (p = environ; *p; ++p)			fprintf(stderr, "\t%s\n", *p);		fprintf(stderr, "-----------------------------------------\n");	}	/*	 * Flush stdio channels just before fork, to avoid double-output	 * problems. Ideally we'd use fflush(NULL) here, but there are still a	 * few non-ANSI stdio libraries out there (like SunOS 4.1.x) that	 * coredump if we do. Presently stdout and stderr are the only stdio	 * output channels used by the postmaster, so fflush'ing them should	 * be sufficient.	 */	fflush(stdout);	fflush(stderr);	if ((pid = fork()) == 0)	{							/* child */		if (DoBackend(port))		{			fprintf(stderr, "%s child[%d]: BackendStartup: backend startup failed\n",					progname, (int) getpid());			exit(1);		}		else			exit(0);	}	/* in parent */	if (pid < 0)	{		fprintf(stderr, "%s: BackendStartup: fork failed: %s\n",				progname, strerror(errno));		return STATUS_ERROR;	}	if (DebugLvl)		fprintf(stderr, "%s: BackendStartup: pid %d user %s db %s socket %d\n",				progname, pid, port->user, port->database,				port->sock);	/* Generate a new backend tag for every backend we start */	/*	 * XXX theoretically this could wrap around, if you have the patience	 * to start 2^31 backends ...	 */	NextBackendTag -= 1;	/*	 * Everything's been successful, it's safe to add this backend to our	 * list of backends.	 */	if (!(bn = (Backend *) calloc(1, sizeof(Backend))))	{		fprintf(stderr, "%s: BackendStartup: malloc failed\n",				progname);		ExitPostmaster(1);	}	bn->pid = pid;	bn->cancel_key = MyCancelKey;	DLAddHead(BackendList, DLNewElem(bn));	ActiveBackends = TRUE;	return STATUS_OK;}/* * split_opts -- split a string of options and append it to an argv array * * NB: the string is destructively modified! * * Since no current POSTGRES arguments require any quoting characters, * we can use the simple-minded tactic of assuming each set of space- * delimited characters is a separate argv element. * * If you don't like that, well, we *used* to pass the whole option string * as ONE argument to execl(), which was even less intelligent... */static voidsplit_opts(char **argv, int *argcp, char *s){	int			i = *argcp;	while (s && *s)	{		while (isspace(*s))			++s;		if (*s == '\0')			break;		argv[i++] = s;		while (*s && !isspace(*s))			++s;		if (*s)			*s++ = '\0';	}	*argcp = i;}/* * DoBackend -- set up the backend's argument list and invoke backend main(). * * This used to perform an execv() but we no longer exec the backend; * it's the same executable as the postmaster. * * returns: *		Shouldn't return at all. *		If PostgresMain() fails, return status. */static intDoBackend(Port *port){	char	   *av[ARGV_SIZE * 2];	int			ac = 0;	char		execbuf[MAXPATHLEN];	char		debugbuf[ARGV_SIZE];	char		protobuf[ARGV_SIZE];	char		dbbuf[ARGV_SIZE];	char		optbuf[ARGV_SIZE];	char		ttybuf[ARGV_SIZE];	int			i;	struct timeval now;	struct timezone tz;	/*	 * Let's clean up ourselves as the postmaster child	 */	/* We don't want the postmaster's proc_exit() handlers */	on_exit_reset();		/* ----------------	 *	register signal handlers.	 *	Thanks to the postmaster, these are currently blocked.	 * ----------------	 */	pqsignal(SIGINT, die);	pqsignal(SIGHUP, die);	pqsignal(SIGTERM, die);	pqsignal(SIGPIPE, die);	pqsignal(SIGUSR1, quickdie);	pqsignal(SIGUSR2, Async_NotifyHandler);	pqsignal(SIGFPE, FloatExceptionHandler);	pqsignal(SIGCHLD, SIG_DFL);	pqsignal(SIGTTIN, SIG_DFL);	pqsignal(SIGTTOU, SIG_DFL);	pqsignal(SIGCONT, SIG_DFL);	/* OK, let's unblock our signals, all together now... */	sigprocmask(SIG_SETMASK, &oldsigmask, 0);	/* Close the postmaster sockets */	if (NetServer)		StreamClose(ServerSock_INET);#ifndef __CYGWIN32__	StreamClose(ServerSock_UNIX);#endif	/* Save port etc. for ps status */	MyProcPort = port;	MyProcPid = getpid();	/*	 * Don't want backend to be able to see the postmaster random number	 * generator state.  We have to clobber the static random_seed *and*	 * start a new random sequence in the random() library function.	 */	random_seed = 0;	gettimeofday(&now, &tz);	srandom(now.tv_usec);	/* ----------------	 * Now, build the argv vector that will be given to PostgresMain.	 *	 * The layout of the command line is	 *		postgres [secure switches] -p databasename [insecure switches]	 * where the switches after -p come from the client request.	 * ----------------	 */	StrNCpy(execbuf, Execfile, MAXPATHLEN);	av[ac++] = execbuf;	/*	 * We need to set our argv[0] to an absolute path name because some	 * OS's use this for dynamic loading, like BSDI.  Without it, when we	 * change directories to the database dir, the dynamic loader can't	 * find the base executable and fails. Another advantage is that this	 * changes the 'ps' displayed process name on some platforms.  It does	 * on BSDI.  That's a big win.	 */#ifndef linux	/*	 * This doesn't work on linux and overwrites the only valid pointer to	 * the argv buffer.  See PS_INIT_STATUS macro.	 */	real_argv[0] = Execfile;#endif	/*	 * Pass the requested debugging level along to the backend.  We	 * decrement by one; level one debugging in the postmaster traces	 * postmaster connection activity, and levels two and higher are	 * passed along to the backend.  This allows us to watch only the	 * postmaster or the postmaster and the backend.	 */	if (DebugLvl > 1)	{		sprintf(debugbuf, "-d%d", DebugLvl);		av[ac++] = debugbuf;	}	/*	 * Pass any backend switches specified with -o in the postmaster's own	 * command line.  We assume these are secure. (It's OK to mangle	 * ExtraOptions since we are now in the child process; this won't	 * change the postmaster's copy.)	 */	split_opts(av, &ac, ExtraOptions);	/* Tell the backend what protocol the frontend is using. */	sprintf(protobuf, "-v%u", port->proto);	av[ac++] = protobuf;	/*	 * Tell the backend it is being called from the postmaster, and which	 * database to use.  -p marks the end of secure switches.	 */	av[ac++] = "-p";	StrNCpy(dbbuf, port->database, ARGV_SIZE);	av[ac++] = dbbuf;	/*	 * Pass the (insecure) option switches from the connection request.	 */	StrNCpy(optbuf, port->options, ARGV_SIZE);	split_opts(av, &ac, optbuf);	/*	 * Pass the (insecure) debug output file request.	 *	 * NOTE: currently, this is useless code, since the backend will not	 * honor an insecure -o switch.  I left it here since the backend	 * could be modified to allow insecure -o, given adequate checking	 * that the specified filename is something safe to write on.	 */	if (port->tty[0])	{		StrNCpy(ttybuf, port->tty, ARGV_SIZE);		av[ac++] = "-o";		av[ac++] = ttybuf;	}	av[ac] = (char *) NULL;	if (DebugLvl > 1)	{		fprintf(stderr, "%s child[%d]: starting with (",				progname, MyProcPid);		for (i = 0; i < ac; ++i)			fprintf(stderr, "%s ", av[i]);		fprintf(stderr, ")\n");	}	return (PostgresMain(ac, av, real_argc, real_argv));}/* * ExitPostmaster -- cleanup */static voidExitPostmaster(int status){	/* should cleanup shared memory and kill all backends */	/*	 * Not sure of the semantics here.	When the Postmaster dies, should	 * the backends all be killed? probably not.	 */	if (ServerSock_INET != INVALID_SOCK)		StreamClose(ServerSock_INET);#ifndef __CYGWIN32__	if (ServerSock_UNIX != INVALID_SOCK)		StreamClose(ServerSock_UNIX);#endif	proc_exit(status);}static voiddumpstatus(SIGNAL_ARGS){	Dlelem	   *curr = DLGetHead(PortList);	while (curr)	{		Port	   *port = DLE_VAL(curr);		fprintf(stderr, "%s: dumpstatus:\n", progname);		fprintf(stderr, "\tsock %d\n", port->sock);		curr = DLGetSucc(curr);	}}/* * CharRemap */static charCharRemap(long int ch){	if (ch < 0)		ch = -ch;	ch = ch % 62;	if (ch < 26)		return 'A' + ch;	ch -= 26;	if (ch < 26)		return 'a' + ch;	ch -= 26;	return '0' + ch;}/* * RandomSalt */static voidRandomSalt(char *salt){	long		rand = PostmasterRandom();	*salt = CharRemap(rand % 62);	*(salt + 1) = CharRemap(rand / 62);}/* * PostmasterRandom */static longPostmasterRandom(void){	static bool initialized = false;	if (!initialized)	{		Assert(random_seed != 0 && !IsUnderPostmaster);		srandom(random_seed);		initialized = true;	}	return random() ^ random_seed;}/* * Count up number of child processes. */static intCountChildren(void){	Dlelem	   *curr;	Backend    *bp;	int			mypid = getpid();	int			cnt = 0;	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))	{		bp = (Backend *) DLE_VAL(curr);		if (bp->pid != mypid)			cnt++;	}	return cnt;}

⌨️ 快捷键说明

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