/* * 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", ¶m->startptr.xlogid, ¶m->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 }
/* ---------- * 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); }
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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }