SysLogger subprocess - Mailing list pgsql-hackers
From | Andreas Pflug |
---|---|
Subject | SysLogger subprocess |
Date | |
Msg-id | 40F6D462.1020708@pse-consulting.de Whole thread Raw |
Responses |
Re: SysLogger subprocess
(Alvaro Herrera <alvherre@dcc.uchile.cl>)
|
List | pgsql-hackers |
Here's the core of the logger subprocess. - no rotation code so far, all syslogFile handling is for testing only - send_message_to_serverlog needs some careful handling of stderr, in case pipe writing fails or if after a log process restart redirecting stderr fails. In these cases, the original stderr should be used. While looking at pgstat.c to see how to peek for pipe data, I found readpipe=pgStatPipe[0]; select(readPipe+1, ..); which is probably usually the same as select(pgStatPipe[1], ..) This fd arithmetics seem a bit dubious to me. Regards, Andreas /*------------------------------------------------------------------------- * * syslogger.c * * * * Portions Copyright (c) 2004, PostgreSQL Global Development Group * * * IDENTIFICATION * $PostgreSQL: $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include <signal.h> #include <time.h> #include <unistd.h> #include "libpq/pqsignal.h" #include "miscadmin.h" #include "postmaster/postmaster.h" #include "storage/pmsignal.h" #include "storage/ipc.h" #include "storage/pg_shmem.h" #include "postmaster/syslogger.h" #include "utils/guc.h" /* * GUC parameters */ int SyslogRotationDelay = 24*60*60; int SyslogRotationSize = 10*1024*1024; /* * Flags set by interrupt handlers for later service in the main loop. */ static volatile sig_atomic_t got_SIGHUP = false; static volatile sig_atomic_t rotation_requested = false; static time_t last_rotation_time; static void sigHupHandler(SIGNAL_ARGS); static void rotationHandler(SIGNAL_ARGS); static void SysLoggerMain(void); FILE *syslogFile=0; int syslogPipe[2] = {0, 0}; int realStdErr = 0; /* * Main entry point for bgwriter process * * This is invoked from BootstrapMain, which has already created the basic * execution environment, but not enabled signals yet. */ void SysLoggerMain(void) { /* * Properly accept or ignore signals the postmaster might send us * * Note: we deliberately ignore SIGTERM, because during a standard Unix * system shutdown cycle, init will SIGTERM all processes at once. We * want to wait for the backends to exit, whereupon the postmaster will * tell us it's okay to shut down (via SIGQUIT). * */ pqsignal(SIGHUP, sigHupHandler); /* set flag to read config file */ pqsignal(SIGINT, rotationHandler); /* request log rotation */ pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */ pqsignal(SIGQUIT, SIG_IGN); /* we do not exit on any signal, but wait for the postmaster to end */ pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, SIG_IGN); pqsignal(SIGUSR2, SIG_IGN); /* * Reset some signals that are accepted by postmaster but not here */ pqsignal(SIGCHLD, SIG_DFL); pqsignal(SIGTTIN, SIG_DFL); pqsignal(SIGTTOU, SIG_DFL); pqsignal(SIGCONT, SIG_DFL); pqsignal(SIGWINCH, SIG_DFL); /* !!!!!!!! work to do here */ syslogFile=fopen("/usr/data/pgsql-7.4/pgsql.log", "a+"); /* * if we restarted, our stderr is redirected. * Direct it back to system stderr. */ if (realStdErr != 0) { if (dup2(realStdErr, fileno(stderr)) < 0) { /* * Now we have a real problem: we can't redirect to stderr, * and can't ereport it correctly. */ ereport(PANIC, (errcode_for_file_access(), (errmsg("stderr restoration failed: %m")))); exit(1); } realStdErr=0; } last_rotation_time = time(NULL); /* * main worker loop * */ for (;;) { time_t now; int elapsed_secs; char logbuffer[1024]; char bytesRead; fd_set rfds; struct timeval timeout; int rc; if (got_SIGHUP) { got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); } if (!rotation_requested && SyslogRotationDelay > 0) { /* * Do an unforced rotation if too much time has elapsed * since the last one. */ now = time(NULL); elapsed_secs = now - last_rotation_time; if (elapsed_secs >= SyslogRotationDelay) rotation_requested = true; } if (!rotation_requested && SyslogRotationSize > 0) { if (ftell(syslogFile) >= SyslogRotationSize) rotation_requested = true; } if (rotation_requested) { rotation_requested = false; } FD_ZERO(&rfds); FD_SET(syslogPipe[0], &rfds); timeout.tv_sec=1; timeout.tv_usec=0; /* * Check if data is present */ rc = select(syslogPipe[1], &rfds, NULL, NULL, &timeout); if (rc > 0 && FD_ISSET(syslogPipe[0], &rfds)) { bytesRead = piperead(syslogPipe[0], logbuffer, sizeof(logbuffer)); if (bytesRead > 0) { if (fwrite(logbuffer, 1, bytesRead, syslogFile) < 1) ereport(FATAL, (errcode_for_file_access(), errmsg("fwrite to logfile failed in system logger: %m"))); fflush(syslogFile); if (Log_destination & LOG_DESTINATION_STDERR) { fwrite(logbuffer, 1, bytesRead, stderr); fflush(stderr); } } else if (bytesRead < 0 && errno != EINTR) { ereport(FATAL, (errcode_for_socket_access(), errmsg("could not read from system logger pipe: %m"))); } continue; } if (rc < 0 && errno != EINTR) { ereport(FATAL, (errcode_for_socket_access(), errmsg("select() failed in system logger: %m"))); exit(1); } /* * If postmaster died, there's nothing to log any more. * We check this only after pipe timeouts to receive as much as possible * from the pipe. */ if (!PostmasterIsAlive(true)) { if (syslogFile) fclose(syslogFile); exit(1); } } } int SysLogger_Start(void) { pid_t sysloggerPid; if (!syslogPipe[0]) { if (pgpipe(syslogPipe) < 0) ereport(FATAL, (errcode_for_file_access(), (errmsg("pipe for syslogging not created: %m")))); } 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(); /* Drop our connection to postmaster's shared memory, as well */ PGSharedMemoryDetach(); // closesocket(syslogPipe[1]); /* do the work */ SysLoggerMain(); break; #endif default: /* now we redirect stderr, if not done already */ if (realStdErr == 0) { realStdErr = dup(fileno(stderr)); if (realStdErr < 0) ereport(FATAL, (errcode_for_file_access(), (errmsg("stderr duplication failed: %m")))); if (dup2(syslogPipe[1], fileno(stdout)) < 0) ereport(FATAL, (errcode_for_file_access(), (errmsg("stdout pipe redirection failed: %m")))); if (dup2(syslogPipe[1], fileno(stderr)) < 0) ereport(FATAL, (errcode_for_file_access(), (errmsg("stderr pipe redirection failed: %m")))); } return (int) sysloggerPid; } /* shouldn't get here */ return 0; } /* -------------------------------- * signal handler routines * -------------------------------- */ /* SIGHUP: set flag to re-read config file at next convenient time */ static void sigHupHandler(SIGNAL_ARGS) { got_SIGHUP = true; } /* SIGINT: set flag to rotate logfile */ static void rotationHandler(SIGNAL_ARGS) { rotation_requested = true; }
pgsql-hackers by date: