Пример #1
0
/*
 * Initiate background process for receiving xlog during the backup.
 * The background stream will use its own database connection so we can
 * stream the logfile in parallel with the backups.
 */
static void
StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
{
	logstreamer_param *param;

	param = xmalloc0(sizeof(logstreamer_param));
	param->timeline = timeline;
	param->sysidentifier = sysidentifier;

	/* Convert the starting position */
	if (sscanf(startpos, "%X/%X", &param->startptr.xlogid, &param->startptr.xrecoff) != 2)
	{
		fprintf(stderr, _("%s: invalid format of xlog location: %s\n"),
				progname, startpos);
		disconnect_and_exit(1);
	}
	/* Round off to even segment position */
	param->startptr.xrecoff -= param->startptr.xrecoff % XLOG_SEG_SIZE;

#ifndef WIN32
	/* Create our background pipe */
	if (pgpipe(bgpipe) < 0)
	{
		fprintf(stderr, _("%s: could not create pipe for background process: %s\n"),
				progname, strerror(errno));
		disconnect_and_exit(1);
	}
#endif

	/* Get a second connection */
	param->bgconn = GetConnection();

	/*
	 * Always in plain format, so we can write to basedir/pg_xlog. But the
	 * directory entry in the tar file may arrive later, so make sure it's
	 * created before we start.
	 */
	snprintf(param->xlogdir, sizeof(param->xlogdir), "%s/pg_xlog", basedir);
	verify_dir_is_empty_or_create(param->xlogdir);

	/*
	 * Start a child process and tell it to start streaming. On Unix, this is
	 * a fork(). On Windows, we create a thread.
	 */
#ifndef WIN32
	bgchild = fork();
	if (bgchild == 0)
	{
		/* in child process */
		exit(LogStreamerMain(param));
	}
	else if (bgchild < 0)
	{
		fprintf(stderr, _("%s: could not create background process: %s\n"),
				progname, strerror(errno));
		disconnect_and_exit(1);
	}

	/*
	 * Else we are in the parent process and all is well.
	 */
#else							/* WIN32 */
	bgchild = _beginthreadex(NULL, 0, (void *) LogStreamerMain, param, 0, NULL);
	if (bgchild == 0)
	{
		fprintf(stderr, _("%s: could not create background thread: %s\n"),
				progname, strerror(errno));
		disconnect_and_exit(1);
	}
#endif
}
Пример #2
0
/* ----------
 * main
 * ----------
 */
int
main(int argc, char *const argv[])
{
	char	   *cp1;
	char	   *cp2;
	int			c;
	int			errors = 0;
	extern int	optind;
	extern char *optarg;


#ifdef WIN32
	WSADATA		wsaData;
	int			err;
#endif


#ifdef WIN32
	if (argc >= 2 && !strcmp(argv[1], "-service"))
	{
		win32_servicestart();
		exit(0);
	}
	if (argc >= 2 && !strcmp(argv[1], "-subservice"))
	{
		win32_isservice = 1;
		argc--;
		argv++;
	}
	if (argc >= 2 && argc <= 4 && (
								   !strcmp(argv[1], "-regservice") ||
								   !strcmp(argv[1], "-unregservice") ||
								   !strcmp(argv[1], "-addengine") ||
								   !strcmp(argv[1], "-delengine") ||
								   !strcmp(argv[1], "-listengines")))
	{
		win32_serviceconfig(argc, argv);
	}
#endif

	InitializeConfOptions();

	while ((c = getopt(argc, argv, "f:a:d:s:t:g:c:p:o:q:r:l:x:hv?")) != EOF)
	{
		switch (c)
		{
			case '?':
				Usage(argv);
			case 'q':
				set_config_option("quit_sync_provider", optarg);
				break;

			case 'r':
				set_config_option("quit_sync_finalsync", optarg);
				break;

			case 'f':
				ProcessConfigFile(optarg);
				break;

			case 'a':
				set_config_option("archive_dir", optarg);
				break;

			case 'd':
				set_config_option("log_level", optarg);
				break;

			case 's':
				set_config_option("sync_interval", optarg);
				break;

			case 't':
				set_config_option("sync_interval_timeout", optarg);
				break;

			case 'g':
				set_config_option("sync_group_maxsize", optarg);
				break;

			case 'c':
				set_config_option("vac_frequency", optarg);
				break;

			case 'p':
				set_config_option("pid_file", optarg);
				break;

			case 'o':
				set_config_option("desired_sync_time", optarg);
				break;

			case 'l':
				set_config_option("lag_interval", optarg);
				break;

			case 'h':
				errors++;
				break;

			case 'v':
				printf("slon version %s\n", SLONY_I_VERSION_STRING);
				exit(0);
				break;

			case 'x':
				set_config_option("command_on_logarchive", optarg);
				break;

			default:
				fprintf(stderr, "unknown option '%c'\n", c);
				errors++;
				break;
		}
	}

	/*
	 * Make sure the sync interval timeout isn't too small.
	 */
	if (sync_interval_timeout != 0 && sync_interval_timeout <= sync_interval)
		sync_interval_timeout = sync_interval * 2;

	/*
	 * Remember the cluster name and build the properly quoted namespace
	 * identifier
	 */
	slon_pid = getpid();
#ifndef WIN32
	if (pthread_mutex_init(&slon_watchdog_lock, NULL) < 0)
	{
		slon_log(SLON_FATAL, "slon: pthread_mutex_init() - %s\n",
				 strerror(errno));
		exit(-1);
	}
	slon_watchdog_pid = slon_pid;
	slon_worker_pid = -1;
#endif
	main_argv = argv;

	if ((char *) argv[optind])
	{
		set_config_option("cluster_name", (char *) argv[optind]);
		set_config_option("conn_info", (char *) argv[++optind]);
	}

	if (rtcfg_cluster_name != NULL)
	{
		rtcfg_namespace = malloc(strlen(rtcfg_cluster_name) * 2 + 4);
		cp2 = rtcfg_namespace;
		*cp2++ = '"';
		*cp2++ = '_';
		for (cp1 = (char *) rtcfg_cluster_name; *cp1; cp1++)
		{
			if (*cp1 == '"')
				*cp2++ = '"';
			*cp2++ = *cp1;
		}
		*cp2++ = '"';
		*cp2 = '\0';
	}
	else
	{
		errors++;
	}

	slon_log(SLON_CONFIG, "main: slon version %s starting up\n",
			 SLONY_I_VERSION_STRING);

	/*
	 * Remember the connection information for the local node.
	 */
	if (rtcfg_conninfo == NULL)
	{
		errors++;
	}

	if (errors != 0)
	{
		Usage(argv);
	}

#ifdef WIN32

	/*
	 * Startup the network subsystem, in case our libpq doesn't
	 */
	err = WSAStartup(MAKEWORD(1, 1), &wsaData);
	if (err != 0)
	{
		slon_log(SLON_FATAL, "main: Cannot start the network subsystem - %d\n", err);
		exit(-1);
	}
#endif

	if (pid_file)
	{
		FILE	   *pidfile;

		pidfile = fopen(pid_file, "w");
		if (pidfile)
		{
			fprintf(pidfile, "%d\n", slon_pid);
			fclose(pidfile);
		}
		else
		{
			slon_log(SLON_FATAL, "Cannot open pid_file \"%s\"\n", pid_file);
			exit(-1);
		}
	}

	/*
	 * Create the pipe used to kick the workers scheduler thread
	 */
	if (pgpipe(sched_wakeuppipe) < 0)
	{
		slon_log(SLON_FATAL, "slon: sched_wakeuppipe create failed -(%d) %s\n", errno, strerror(errno));
		slon_exit(-1);
	}

	if (!PQisthreadsafe())
	{
		slon_log(SLON_FATAL, "slon: libpq was not compiled with thread safety enabled (normally: --enable-thread-safety).  slon is a multithreaded application requiring thread-safe libpq\n");
		slon_exit(-1);
	}

	if (!PQisthreadsafe())
	{
		slon_log(SLON_FATAL, "slon: libpq was not compiled with --enable-thread-safety. Slony-I requires a thread enabled libpq\n");
		slon_exit(-1);
	}

	/*
	 * There is no watchdog process on win32. We delegate restarting and other
	 * such tasks to the Service Control Manager. And win32 doesn't support
	 * signals, so we don't need to catch them...
	 */
#ifndef WIN32
	SlonWatchdog();
#else
	SlonMain();
#endif
	exit(0);
}
Пример #3
0
int RB_LIBYARN_start(bool isforked)
{
	int res = FUNC_RETURN_OK;

	/* If SIGCHLD is received, ResBrokerExits is set true, which means resource
	 * broker process might quits, so before starting new one, we have to do some
	 * clean up. */
	if ( ResBrokerExits )
	{
		/* Check if current resource broker process exits. */
		if ( ResBrokerPID > 0 )
		{
			int status = 0;
			if( ResBrokerPID != waitpid(ResBrokerPID, &status, WNOHANG) )
			{
				return FUNC_RETURN_OK;
			}
			if (WIFEXITED(status) && WEXITSTATUS(status))
			{
				elog(FATAL, "YARN mode resource broker failed to start resource "
							"broker process. error=%d",
							WEXITSTATUS(status));
			}
		}

		/* Resource broker quits, clean up the pipes and status. */
		ResBrokerPID   = -1;
		ResBrokerExits = false;

		/* Check and clear resource broker pending status. */
		clearPendingResourceRequestInRootQueue();
		PipeReceivePending = false;
	}

	/* Start the resource broker process. */
	if ( ResBrokerPID == -1 )
	{
		/* Close possible open pipes. */
		if ( ResBrokerRequestPipe[0] != -1 )
		{
			close(ResBrokerRequestPipe[0]);
			close(ResBrokerRequestPipe[1]);
		}
		if ( ResBrokerNotifyPipe[0] != -1 )
		{
			close(ResBrokerNotifyPipe[0]);
			close(ResBrokerNotifyPipe[1]);
		}

		/* Create pipe for communication between RM and RB. */
		ResBrokerRequestPipe[0] = -1;
		ResBrokerRequestPipe[1] = -1;
		ResBrokerNotifyPipe[0]  = -1;
		ResBrokerNotifyPipe[1]  = -1;

		res = pgpipe(ResBrokerRequestPipe);
		if ( res < 0 )
		{
			elog(FATAL, "YARN mode resource broker failed to create pipe between "
						"resource manager and resource broker. errno %d",
						errno);
		}

		res = pgpipe(ResBrokerNotifyPipe);
		if ( res < 0 )
		{
			elog(FATAL, "YARN mode resource broker failed to create pipe between "
						"resource manager and resource broker. errno %d",
						 errno);
		}

		ResBrokerExits     = false;
		ResBrokerParentPID = getpid();
		ResBrokerPID       = fork_process();

		switch(ResBrokerPID)
		{
		case 0:
			exit(ResBrokerMain());
		default:
			PipeReceivePending = false;
			elog(LOG, "YARN mode resource broker created resource broker process "
					  "PID=%d.",
					  ResBrokerPID);
		}

		return FUNC_RETURN_OK;
	}

	return FUNC_RETURN_OK;
}
Пример #4
0
/*
 * Postmaster subroutine to start a syslogger subprocess.
 */
int
syslog_start(void)
{
	pid_t pid;
	char *filename;

	if (!log_collector)
		return 0;

	/*
	 * If first time through, create the pipe which will receive stderr
	 * output. If syslog crashes and needs to be restarted, we continue to 
	 * use the same pipe. Indeed must do so, since extant backends will be
	 * writing into that pipe.
	 *
	 * This means the postmaster must continue to hold the read end of the
	 * pipe open, so we can pass it down to the reincarnated syslogger. This
	 * is a bit klugy but we have little choice.
	 */
#ifndef WIN32
	if (syslog_pipe[0] < 0) {
		if (pgpipe(syslog_pipe) < 0)
			ereport(FATAL, (
			errcode_sock_access(),
			errmsg("could not create pipe for syslog: %m")));
	}
#else
	if (!syslog_pipe[0]) {
		SECURITY_ATTRIBUTES sa;

		memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
		sa.nLength = sizeof(SECURITY_ATTRIBUTES);
		sa.bInheritHandle = TRUE;

		if (!CreatePipe(&syslog_pipe[0], &syslog_pipe[1], &sa, 32768))
			ereport(FATAL, (
			errcode_file_access(),
			errmsg("could not create pipe for syslog: %m")));
	}
#endif

	/*
	 * Create log directory if not present; ignore errors
	 */
	mkdir(log_directory, S_IRWXU);

	/*
	 * The initial logfile is created right in the postmaster, to verify i
	 * that the log_directory is writable.
	 */
	filename = logfile_getname(time(NULL), NULL);
	syslog_file = logfile_open(filename, "a", false);
	pfree(filename);

#ifdef EXEC_BACKEND
	switch ((pid = syslog_forkexec())) {
#else
	switch ((pid = fork_process())) {
#endif
	case -1:
		ereport(LOG, (errmsg("could not fork system logger: %m")));
		return 0;

#ifndef EXEC_BACKEND
	case 0:
		/* in postmaster child ... */
		/* Close the postmaster's sockets */
		close_ports(true);

		/* Lose the postmaster's on-exit routines */
		on_exit_reset();

		/* Drop our connection to postmaster's shared memory */
		shm_child_detach();

		/* do the work */
		syslog_main(0, NULL);
		break;
#endif

	default:
		/* success, in postmaster */

		/* now we redirect stderr, if not done already */
		if (!redirection_done) {
#ifndef WIN32
			fflush(stdout);
			if (dup2(syslog_pipe[1], fileno(stdout)) < 0) {
				ereport(FATAL, (
				errcode_file_access(),
				errmsg("could not redirect stdout: %m")));
			}

			fflush(stderr);
			if (dup2(syslog_pipe[1], fileno(stderr)) < 0) {
				ereport(FATAL, (
				errcode_file_access(),
				errmsg("could not redirect stderr: %m")));
			}

			/* Now we are done with the write end of pipe */
			close(syslog_pipe[1]);
			syslog_pipe[1] = -1;
#else
			int fd;

			/*
			 * open the pipe in binary mode and make sure stderr is binary
			 * after it's been dup'ed into, to avoid disturbing the pipe
			 * chunking protocol.
			 */
			fflush(stderr);
			fd = _open_osfhandle((intptr_t) syslog_pipe[1], _O_APPEND | _O_BINARY);
			if (dup2(fd, _fileno(stderr)) < 0)
				ereport(FATAL, (
				errcode_file_access(),
				errmsg("could not redirect stderr: %m")));

			close(fd);
			_setmode(_fileno(stderr), _O_BINARY);

			/* Now we are done with the write end of the pipe. */
			CloseHandle(syslog_pipe[1]);
			syslog_pipe[1] = 0;
#endif
			redirection_done = true;
		}

		/* postmaster will never write the file; close it */
		fclose(syslog_file);
		syslog_file = NULL;
		return (int) pid;
	}

	/* we should never reach here */
	return 0;
}


#ifdef EXEC_BACKEND

/*
 * syslog_forkexec() -
 *
 * Format up the arglist for, then fork and exec, a syslogger process
 */
static pid_t
syslog_forkexec(void)
{
	char *av[10];
	int ac = 0;
	char filenobuf[32];

	av[ac++] = "postgres";
	av[ac++] = "--forklog";
	av[ac++] = NULL;			/* filled in by master_forkexec */

	/* static variables (those not passed by write_backend_variables) */
#ifndef WIN32
	if (syslog_file != NULL)
		snprintf(filenobuf, sizeof(filenobuf), "%d", fileno(syslog_file));
	else
		strcpy(filenobuf, "-1");

#else	/* WIN32 */
	if (syslog_file != NULL)
		snprintf(filenobuf, sizeof(filenobuf), "%ld",
			(long) _get_osfhandle(_fileno(syslog_file)));
	else
		strcpy(filenobuf, "0");

#endif   /* WIN32 */
	av[ac++] = filenobuf;
	av[ac] = NULL;
	ASSERT(ac < lengthof(av));

	return master_forkexec(ac, av);
}
/*
 * Postmaster subroutine to start a syslogger subprocess.
 */
int
SysLogger_Start(void)
{
	pid_t		sysloggerPid;
	char	   *filename;

	if (!Logging_collector)
		return 0;

	/*
	 * If first time through, create the pipe which will receive stderr
	 * output.
	 *
	 * If the syslogger crashes and needs to be restarted, we continue to use
	 * the same pipe (indeed must do so, since extant backends will be writing
	 * into that pipe).
	 *
	 * This means the postmaster must continue to hold the read end of the
	 * pipe open, so we can pass it down to the reincarnated syslogger. This
	 * is a bit klugy but we have little choice.
	 */
#ifndef WIN32
	if (syslogPipe[0] < 0)
	{
		if (pgpipe(syslogPipe) < 0)
			ereport(FATAL,
					(errcode_for_socket_access(),
					 (errmsg("could not create pipe for syslog: %m"))));
	}
#else
	if (!syslogPipe[0])
	{
		SECURITY_ATTRIBUTES sa;

		memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
		sa.nLength = sizeof(SECURITY_ATTRIBUTES);
		sa.bInheritHandle = TRUE;

		if (!CreatePipe(&syslogPipe[0], &syslogPipe[1], &sa, 32768))
			ereport(FATAL,
					(errcode_for_file_access(),
					 (errmsg("could not create pipe for syslog: %m"))));
	}
#endif

	/*
	 * Create log directory if not present; ignore errors
	 */
	mkdir(Log_directory, S_IRWXU);

	/*
	 * The initial logfile is created right in the postmaster, to verify that
	 * the Log_directory is writable.  We save the reference time so that
	 * the syslogger child process can recompute this file name.
	 *
	 * It might look a bit strange to re-do this during a syslogger restart,
	 * but we must do so since the postmaster closed syslogFile after the
	 * previous fork (and remembering that old file wouldn't be right anyway).
	 * Note we always append here, we won't overwrite any existing file.  This
	 * is consistent with the normal rules, because by definition this is not
	 * a time-based rotation.
	 */
	first_syslogger_file_time = time(NULL);
	filename = logfile_getname(first_syslogger_file_time, NULL);

	syslogFile = logfile_open(filename, "a", false);

	pfree(filename);

#ifdef EXEC_BACKEND
	switch ((sysloggerPid = syslogger_forkexec()))
#else
	switch ((sysloggerPid = fork_process()))
#endif
	{
		case -1:
			ereport(LOG,
					(errmsg("could not fork system logger: %m")));
			return 0;

#ifndef EXEC_BACKEND
		case 0:
			/* in postmaster child ... */
			/* Close the postmaster's sockets */
			ClosePostmasterPorts(true);

			/* Lose the postmaster's on-exit routines */
			on_exit_reset();

			/* Drop our connection to postmaster's shared memory, as well */
			PGSharedMemoryDetach();

			/* do the work */
			SysLoggerMain(0, NULL);
			break;
#endif

		default:
			/* success, in postmaster */

			/* now we redirect stderr, if not done already */
			if (!redirection_done)
			{
#ifndef WIN32
				fflush(stdout);
				if (dup2(syslogPipe[1], fileno(stdout)) < 0)
					ereport(FATAL,
							(errcode_for_file_access(),
							 errmsg("could not redirect stdout: %m")));
				fflush(stderr);
				if (dup2(syslogPipe[1], fileno(stderr)) < 0)
					ereport(FATAL,
							(errcode_for_file_access(),
							 errmsg("could not redirect stderr: %m")));
				/* Now we are done with the write end of the pipe. */
				close(syslogPipe[1]);
				syslogPipe[1] = -1;
#else
				int			fd;

				/*
				 * open the pipe in binary mode and make sure stderr is binary
				 * after it's been dup'ed into, to avoid disturbing the pipe
				 * chunking protocol.
				 */
				fflush(stderr);
				fd = _open_osfhandle((intptr_t) syslogPipe[1],
									 _O_APPEND | _O_BINARY);
				if (dup2(fd, _fileno(stderr)) < 0)
					ereport(FATAL,
							(errcode_for_file_access(),
							 errmsg("could not redirect stderr: %m")));
				close(fd);
				_setmode(_fileno(stderr), _O_BINARY);
				/*
				 * Now we are done with the write end of the pipe.
				 * CloseHandle() must not be called because the preceding
				 * close() closes the underlying handle.
				 */
				syslogPipe[1] = 0;
#endif
				redirection_done = true;
			}

			/* postmaster will never write the file; close it */
			fclose(syslogFile);
			syslogFile = NULL;
			return (int) sysloggerPid;
	}

	/* we should never reach here */
	return 0;
}
Пример #6
0
/*
 * Postmaster subroutine to start a syslogger subprocess.
 */
int
SysLogger_Start(void)
{
	pid_t		sysloggerPid;
	char	   *filename;

	if (!Redirect_stderr)
		return 0;

	/*
	 * If first time through, create the pipe which will receive stderr
	 * output.
	 *
	 * If the syslogger crashes and needs to be restarted, we continue to use
	 * the same pipe (indeed must do so, since extant backends will be
	 * writing into that pipe).
	 *
	 * This means the postmaster must continue to hold the read end of the
	 * pipe open, so we can pass it down to the reincarnated syslogger.
	 * This is a bit klugy but we have little choice.
	 */
#ifndef WIN32
	if (syslogPipe[0] < 0)
	{
		if (pgpipe(syslogPipe) < 0)
			ereport(FATAL,
					(errcode_for_socket_access(),
				  (errmsg("could not create pipe for syslog: %m"))));
	}
#else
	if (!syslogPipe[0])
	{
		SECURITY_ATTRIBUTES sa;

		memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
		sa.nLength = sizeof(SECURITY_ATTRIBUTES);
		sa.bInheritHandle = TRUE;

		if (!CreatePipe(&syslogPipe[0], &syslogPipe[1], &sa, 32768))
			ereport(FATAL,
					(errcode_for_file_access(),
				  (errmsg("could not create pipe for syslog: %m"))));
	}
#endif

	/*
	 * create log directory if not present; ignore errors
	 */
	if (is_absolute_path(Log_directory))
		mkdir(Log_directory, 0700);
	else
	{
		filename = palloc(MAXPGPATH);
		snprintf(filename, MAXPGPATH, "%s/%s", DataDir, Log_directory);
		mkdir(filename, 0700);
		pfree(filename);
	}

	/*
	 * The initial logfile is created right in the postmaster, to verify
	 * that the Log_directory is writable.
	 */
	filename = logfile_getname(time(NULL));

	syslogFile = fopen(filename, "a");

	if (!syslogFile)
		ereport(FATAL,
				(errcode_for_file_access(),
				 (errmsg("could not create log file \"%s\": %m",
						 filename))));

	setvbuf(syslogFile, NULL, LBF_MODE, 0);

	pfree(filename);

	/*
	 * Now we can fork off the syslogger subprocess.
	 */
	fflush(stdout);
	fflush(stderr);

#ifdef __BEOS__
	/* Specific beos actions before backend startup */
	beos_before_backend_startup();
#endif

#ifdef EXEC_BACKEND
	switch ((sysloggerPid = syslogger_forkexec()))
#else
	switch ((sysloggerPid = fork()))
#endif
	{
		case -1:
#ifdef __BEOS__
			/* Specific beos actions */
			beos_backend_startup_failed();
#endif
			ereport(LOG,
					(errmsg("could not fork system logger: %m")));
			return 0;

#ifndef EXEC_BACKEND
		case 0:
			/* in postmaster child ... */
#ifdef __BEOS__
			/* Specific beos actions after backend startup */
			beos_backend_startup();
#endif
			/* Close the postmaster's sockets */
			ClosePostmasterPorts(true);

			/* Drop our connection to postmaster's shared memory, as well */
			PGSharedMemoryDetach();

			/* do the work */
			SysLoggerMain(0, NULL);
			break;
#endif

		default:
			/* success, in postmaster */

			/* now we redirect stderr, if not done already */
			if (!redirection_done)
			{
#ifndef WIN32
				fflush(stdout);
				if (dup2(syslogPipe[1], fileno(stdout)) < 0)
					ereport(FATAL,
							(errcode_for_file_access(),
							 errmsg("could not redirect stdout: %m")));
				fflush(stderr);
				if (dup2(syslogPipe[1], fileno(stderr)) < 0)
					ereport(FATAL,
							(errcode_for_file_access(),
							 errmsg("could not redirect stderr: %m")));
				/* Now we are done with the write end of the pipe. */
				close(syslogPipe[1]);
				syslogPipe[1] = -1;
#else
				int			fd;

				fflush(stderr);
				fd = _open_osfhandle((long) syslogPipe[1],
									 _O_APPEND | _O_TEXT);
				if (dup2(fd, _fileno(stderr)) < 0)
					ereport(FATAL,
							(errcode_for_file_access(),
							 errmsg("could not redirect stderr: %m")));
				close(fd);
				/* Now we are done with the write end of the pipe. */
				CloseHandle(syslogPipe[1]);
				syslogPipe[1] = 0;
#endif
				redirection_done = true;
			}

			/* postmaster will never write the file; close it */
			fclose(syslogFile);
			syslogFile = NULL;
			return (int) sysloggerPid;
	}

	/* we should never reach here */
	return 0;
}
Пример #7
0
/*
 * Postmaster subroutine to start a syslogger subprocess.
 */
int
SysLogger_Start(void)
{
	pid_t		sysloggerPid;
	char	   *filename;

	if (!Redirect_stderr)
		return 0;

	/*
	 * If first time through, create the pipe which will receive stderr
	 * output.
	 *
	 * If the syslogger crashes and needs to be restarted, we continue to use
	 * the same pipe (indeed must do so, since extant backends will be writing
	 * into that pipe).
	 *
	 * This means the postmaster must continue to hold the read end of the
	 * pipe open, so we can pass it down to the reincarnated syslogger. This
	 * is a bit klugy but we have little choice.
	 */
#ifndef WIN32
	if (syslogPipe[0] < 0)
	{
		if (pgpipe(syslogPipe) < 0)
			ereport(FATAL,
					(errcode_for_socket_access(),
					 (errmsg("could not create pipe for syslog: %m"))));
	}
#else
	if (!syslogPipe[0])
	{
		SECURITY_ATTRIBUTES sa;

		memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
		sa.nLength = sizeof(SECURITY_ATTRIBUTES);
		sa.bInheritHandle = TRUE;

		if (!CreatePipe(&syslogPipe[0], &syslogPipe[1], &sa, 32768))
			ereport(FATAL,
					(errcode_for_file_access(),
					 (errmsg("could not create pipe for syslog: %m"))));
	}
#endif

	/*
	 * Create log directory if not present; ignore errors
	 */
	mkdir(Log_directory, 0700);

	/*
	 * The initial logfile is created right in the postmaster, to verify that
	 * the Log_directory is writable.
	 */
	filename = logfile_getname(time(NULL));

	syslogFile = fopen(filename, "a");

	if (!syslogFile)
		ereport(FATAL,
				(errcode_for_file_access(),
				 (errmsg("could not create log file \"%s\": %m",
						 filename))));

	setvbuf(syslogFile, NULL, LBF_MODE, 0);

	pfree(filename);

#ifdef EXEC_BACKEND
	switch ((sysloggerPid = syslogger_forkexec()))
#else
	switch ((sysloggerPid = fork_process()))
#endif
	{
		case -1:
			ereport(LOG,
					(errmsg("could not fork system logger: %m")));
			return 0;

#ifndef EXEC_BACKEND
		case 0:
			/* in postmaster child ... */
			/* Close the postmaster's sockets */
			ClosePostmasterPorts(true);

			/* Lose the postmaster's on-exit routines */
			on_exit_reset();

			/* Drop our connection to postmaster's shared memory, as well */
			PGSharedMemoryDetach();

			/* do the work */
			SysLoggerMain(0, NULL);
			break;
#endif

		default:
			/* success, in postmaster */

			/* now we redirect stderr, if not done already */
			if (!redirection_done)
			{
#ifndef WIN32
				fflush(stdout);
				if (dup2(syslogPipe[1], fileno(stdout)) < 0)
					ereport(FATAL,
							(errcode_for_file_access(),
							 errmsg("could not redirect stdout: %m")));
				fflush(stderr);
				if (dup2(syslogPipe[1], fileno(stderr)) < 0)
					ereport(FATAL,
							(errcode_for_file_access(),
							 errmsg("could not redirect stderr: %m")));
				/* Now we are done with the write end of the pipe. */
				close(syslogPipe[1]);
				syslogPipe[1] = -1;
#else
				int			fd;

				/*
				 * open the pipe in binary mode and make sure
				 * stderr is binary after it's been dup'ed into, to avoid
				 * disturbing the pipe chunking protocol.
				 */
				fflush(stderr);
				fd = _open_osfhandle((long) syslogPipe[1],
									 _O_APPEND | _O_BINARY);
				if (dup2(fd, _fileno(stderr)) < 0)
					ereport(FATAL,
							(errcode_for_file_access(),
							 errmsg("could not redirect stderr: %m")));
				close(fd);
				_setmode(_fileno(stderr),_O_BINARY);
				/* Now we are done with the write end of the pipe. */
				CloseHandle(syslogPipe[1]);
				syslogPipe[1] = 0;
#endif
				redirection_done = true;
			}

			/* postmaster will never write the file; close it */
			fclose(syslogFile);
			syslogFile = NULL;
			return (int) sysloggerPid;
	}

	/* we should never reach here */
	return 0;
}
Пример #8
0
/*
 * popen_with_stderr
 *
 * standard popen doesn't redirect stderr from the child process.
 * we need stderr in order to display the error that child process
 * encountered and show it to the user. This is, therefore, a wrapper
 * around a set of file descriptor redirections and a fork.
 *
 * if 'forwrite' is set then we set the data pipe write side on the
 * parent. otherwise, we set the read side on the parent.
 */
int
popen_with_stderr(int *pipes, const char *exe, bool forwrite)
{
	int data[2];	/* pipe to send data child <--> parent */
	int err[2];		/* pipe to send errors child --> parent */
	int pid = -1;

	const int READ = 0;
	const int WRITE = 1;

	if (pgpipe(data) < 0)
		return -1;

	if (pgpipe(err) < 0)
	{
		close(data[READ]);
		close(data[WRITE]);
		return -1;
	}
#ifndef WIN32

	pid = fork();

	if (pid > 0) /* parent */
	{

		if (forwrite)
		{
			/* parent writes to child */
			close(data[READ]);
			pipes[EXEC_DATA_P] = data[WRITE];
		}
		else
		{
			/* parent reads from child */
			close(data[WRITE]);
			pipes[EXEC_DATA_P] = data[READ];
		}

		close(err[WRITE]);
		pipes[EXEC_ERR_P] = err[READ];

		return pid;
	}
	else if (pid == 0) /* child */
	{

		/*
		 * set up the data pipe
		 */
		if (forwrite)
		{
			close(data[WRITE]);
			close(fileno(stdin));

			/* assign pipes to parent to stdin */
			if (dup2(data[READ], fileno(stdin)) < 0)
			{
				perror("dup2 error");
				exit(EXIT_FAILURE);
			}

			/* no longer needed after the duplication */
			close(data[READ]);
		}
		else
		{
			close(data[READ]);
			close(fileno(stdout));

			/* assign pipes to parent to stdout */
			if (dup2(data[WRITE], fileno(stdout)) < 0)
			{
				perror("dup2 error");
				exit(EXIT_FAILURE);
			}

			/* no longer needed after the duplication */
			close(data[WRITE]);
		}

		/*
		 * now set up the error pipe
		 */
		close(err[READ]);
		close(fileno(stderr));

		if (dup2(err[WRITE], fileno(stderr)) < 0)
		{
			if(forwrite)
				close(data[WRITE]);
			else
				close(data[READ]);

			perror("dup2 error");
			exit(EXIT_FAILURE);
		}

		close(err[WRITE]);

		/* go ahead and execute the user command */
		execl("/bin/sh", "sh", "-c", exe, NULL);

		/* if we're here an error occurred */
		exit(EXIT_FAILURE);
	}
	else
	{
		if(forwrite)
		{
			close(data[WRITE]);
			close(data[READ]);
		}
		else
		{
			close(data[READ]);
			close(data[WRITE]);
		}
		close(err[READ]);
		close(err[WRITE]);

		return -1;
	}
#endif

	return pid;
}