diff options
Diffstat (limited to 'src/backend/postmaster/postmaster.c')
-rw-r--r-- | src/backend/postmaster/postmaster.c | 939 |
1 files changed, 480 insertions, 459 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 7ef3ea4bd71..9726a92fd0e 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -10,38 +10,38 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.24 1996/11/12 06:46:36 bryanh Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.25 1996/11/14 10:24:01 bryanh Exp $ * * NOTES * * Initialization: - * The Postmaster sets up a few shared memory data structures - * for the backends. It should at the very least initialize the - * lock manager. + * The Postmaster sets up a few shared memory data structures + * for the backends. It should at the very least initialize the + * lock manager. * * Synchronization: - * The Postmaster shares memory with the backends and will have to lock - * the shared memory it accesses. The Postmaster should never block - * on messages from clients. - * + * The Postmaster shares memory with the backends and will have to lock + * the shared memory it accesses. The Postmaster should never block + * on messages from clients. + * * Garbage Collection: - * The Postmaster cleans up after backends if they have an emergency - * exit and/or core dump. + * The Postmaster cleans up after backends if they have an emergency + * exit and/or core dump. * * Communication: * *------------------------------------------------------------------------- */ - /* moved here to prevent double define */ -#include <sys/param.h> /* for MAXHOSTNAMELEN on most */ + /* moved here to prevent double define */ +#include <sys/param.h> /* for MAXHOSTNAMELEN on most */ #ifndef MAXHOSTNAMELEN -#include <netdb.h> /* for MAXHOSTNAMELEN on some */ +#include <netdb.h> /* for MAXHOSTNAMELEN on some */ #endif #include "postgres.h" -#include <signal.h> /* for other stuff */ -#include "libpq/pqsignal.h" /* substitute for <signal.h> */ +#include <signal.h> /* for other stuff */ +#include "libpq/pqsignal.h" /* substitute for <signal.h> */ #include <string.h> #include <stdlib.h> @@ -50,13 +50,13 @@ #endif /* !NO_UNISTD_H */ #include <ctype.h> -#include <sys/types.h> /* for fd_set stuff */ -#include <sys/stat.h> /* for umask */ +#include <sys/types.h> /* for fd_set stuff */ +#include <sys/stat.h> /* for umask */ #include <sys/time.h> #include <sys/socket.h> #if defined(USE_LIMITS_H) # include <machine/limits.h> -# define MAXINT INT_MAX +# define MAXINT INT_MAX #else # include <values.h> #endif /* !USE_LIMITS_H */ @@ -103,7 +103,7 @@ * but I left this structure around in case that changed. */ typedef struct bkend { - int pid; /* process id of backend */ + int pid; /* process id of backend */ } Backend; /* list of active backends. For garbage collection only now. */ @@ -113,24 +113,27 @@ static Dllist* BackendList; /* list of ports associated with still open, but incomplete connections */ static Dllist* PortList; -static short PostPortName = -1; -static short ActiveBackends = FALSE; -static int NextBackendId = MAXINT; /* XXX why? */ -static char *progname = (char *) NULL; +static short PostPortName = -1; +static short ActiveBackends = FALSE; +static int NextBackendId = MAXINT; /* XXX why? */ +static char *progname = (char *) NULL; -char *DataDir = (char *) NULL; +char *DataDir; + /* The PGDATA directory user says to use, or defaults to via environment + variable. NULL if no option given and no environment variable set + */ /* * Default Values */ -static char Execfile[MAXPATHLEN] = ""; +static char Execfile[MAXPATHLEN] = ""; -static int ServerSock = INVALID_SOCK; /* stream socket server */ +static int ServerSock = INVALID_SOCK; /* stream socket server */ /* * Set by the -o option */ -static char ExtraOptions[ARGV_SIZE] = ""; +static char ExtraOptions[ARGV_SIZE] = ""; /* * These globals control the behavior of the postmaster in case some @@ -139,8 +142,8 @@ static char ExtraOptions[ARGV_SIZE] = ""; * the postmaster stop (rather than kill) peers and not reinitialize * shared data structures. */ -static int Reinit = 1; -static int SendStop = 0; +static int Reinit = 1; +static int SendStop = 0; static int MultiplexedBackends = 0; static int MultiplexedBackendPort; @@ -160,7 +163,6 @@ static void CleanupProc(int pid, int exitstatus); static int DoExec(StartupInfo *packet, int portFd); static void ExitPostmaster(int status); static void usage(const char *); -static void checkDataDir(void); int ServerLoop(void); int BackendStartup(StartupInfo *packet, Port *port, int *pidPtr); static void send_error_reply(Port *port, const char *errormsg); @@ -168,142 +170,194 @@ static void send_error_reply(Port *port, const char *errormsg); extern char *optarg; extern int optind, opterr; + + +static void +checkDataDir(const char *DataDir, bool *DataDirOK) +{ + if (DataDir == NULL) { + fprintf(stderr, "%s does not know where to find the database system " + "data. You must specify the directory that contains the " + "database system either by specifying the -D invocation " + "option or by setting the PGDATA environment variable.\n\n", + progname); + *DataDirOK = false; + } else { + char path[MAXPATHLEN]; + FILE *fp; + + sprintf(path, "%s%cbase%ctemplate1%cpg_class", + DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR); + fp = fopen(path, "r"); + if (fp == NULL) { + fprintf(stderr, "%s does not find the database system. " + "Expected to find it " + "in the PGDATA directory \"%s\", but unable to open file " + "with pathname \"%s\".\n\n", + progname, DataDir, path); + *DataDirOK = false; + } else { + char *reason; + /* reason ValidatePgVersion failed. NULL if didn't */ + + fclose(fp); + +#ifndef WIN32 + ValidatePgVersion(DataDir, &reason); +#else + reason = NULL; +#endif /* WIN32 */ + if (reason) { + fprintf(stderr, + "Database system in directory %s " + "is not compatible with this version of " + "Postgres, or we are unable to read the " + "PG_VERSION file. " + "Explanation from ValidatePgVersion: %s\n\n", + DataDir, reason); + free(reason); + *DataDirOK = false; + } else *DataDirOK = true; + } + } +} + + + int PostmasterMain(int argc, char *argv[]) { - extern int NBuffers; /* from buffer/bufmgr.c */ - extern bool IsPostmaster; /* from smgr/mm.c */ - int opt; - char *hostName; - int status; - int silentflag = 0; - char hostbuf[MAXHOSTNAMELEN]; + extern int NBuffers; /* from buffer/bufmgr.c */ + extern bool IsPostmaster; /* from smgr/mm.c */ + int opt; + char *hostName; + int status; + int silentflag = 0; + char hostbuf[MAXHOSTNAMELEN]; + bool DataDirOK; /* We have a usable PGDATA value */ #if defined(WIN32) WSADATA WSAData; #endif /* WIN32 */ progname = argv[0]; + IsPostmaster = true; + /* for security, no dir or file created can be group or other accessible */ (void) umask((mode_t) 0077); if (!(hostName = getenv("PGHOST"))) { - if (gethostname(hostbuf, MAXHOSTNAMELEN) < 0) - (void) strcpy(hostbuf, "localhost"); - hostName = hostbuf; + if (gethostname(hostbuf, MAXHOSTNAMELEN) < 0) + (void) strcpy(hostbuf, "localhost"); + hostName = hostbuf; } + + DataDir = getenv("PGDATA"); /* default value */ opterr = 0; while ((opt = getopt(argc, argv, "a:B:b:D:dmM:no:p:Ss")) != EOF) { - switch (opt) { - case 'a': - /* Set the authentication system. */ - be_setauthsvc(optarg); - break; - case 'B': - /* - * The number of buffers to create. Setting this - * option means we have to start each backend with - * a -B # to make sure they know how many buffers - * were allocated. - */ - NBuffers = atol(optarg); - (void) strcat(ExtraOptions, " -B "); - (void) strcat(ExtraOptions, optarg); - break; - case 'b': - /* Set the backend executable file to use. */ - if (!ValidateBackend(optarg)) - strcpy(Execfile, optarg); - else { - fprintf(stderr, "%s: invalid backend \"%s\"\n", - progname, optarg); - exit(2); - } - break; - case 'D': - /* Set PGDATA from the command line. */ - DataDir = optarg; - break; - case 'd': - /* - * Turn on debugging for the postmaster and the backend - * servers descended from it. - */ - if ((optind < argc) && *argv[optind] != '-') { - DebugLvl = atoi(argv[optind]); - optind++; - } - else - DebugLvl = 1; - break; - case 'm': - MultiplexedBackends = 1; - MultiplexedBackendPort = atoi(optarg); - break; - case 'M': - /* ignore this flag. This may be passed in because the - program was run as 'postgres -M' instead of 'postmaster' */ - break; - case 'n': - /* Don't reinit shared mem after abnormal exit */ - Reinit = 0; - break; - case 'o': - /* - * Other options to pass to the backend on the - * command line -- useful only for debugging. - */ - (void) strcat(ExtraOptions, " "); - (void) strcat(ExtraOptions, optarg); - break; - case 'p': - /* Set PGPORT by hand. */ - PostPortName = (short) atoi(optarg); - break; - case 'S': - /* - * Start in 'S'ilent mode (disassociate from controlling tty). - * You may also think of this as 'S'ysV mode since it's most - * badly needed on SysV-derived systems like SVR4 and HP-UX. - */ - silentflag = 1; - break; - case 's': - /* - * In the event that some backend dumps core, - * send SIGSTOP, rather than SIGUSR1, to all - * its peers. This lets the wily post_hacker - * collect core dumps from everyone. - */ - SendStop = 1; - break; - default: - /* usage() never returns */ - usage(progname); - break; - } + switch (opt) { + case 'a': + /* Set the authentication system. */ + be_setauthsvc(optarg); + break; + case 'B': + /* + * The number of buffers to create. Setting this + * option means we have to start each backend with + * a -B # to make sure they know how many buffers + * were allocated. + */ + NBuffers = atol(optarg); + (void) strcat(ExtraOptions, " -B "); + (void) strcat(ExtraOptions, optarg); + break; + case 'b': + /* Set the backend executable file to use. */ + if (!ValidateBackend(optarg)) + strcpy(Execfile, optarg); + else { + fprintf(stderr, "%s: invalid backend \"%s\"\n", + progname, optarg); + exit(2); + } + break; + case 'D': + /* Set PGDATA from the command line. */ + DataDir = optarg; + break; + case 'd': + /* + * Turn on debugging for the postmaster and the backend + * servers descended from it. + */ + if ((optind < argc) && *argv[optind] != '-') { + DebugLvl = atoi(argv[optind]); + optind++; + } + else + DebugLvl = 1; + break; + case 'm': + MultiplexedBackends = 1; + MultiplexedBackendPort = atoi(optarg); + break; + case 'M': + /* ignore this flag. This may be passed in because the + program was run as 'postgres -M' instead of 'postmaster' */ + break; + case 'n': + /* Don't reinit shared mem after abnormal exit */ + Reinit = 0; + break; + case 'o': + /* + * Other options to pass to the backend on the + * command line -- useful only for debugging. + */ + (void) strcat(ExtraOptions, " "); + (void) strcat(ExtraOptions, optarg); + break; + case 'p': + /* Set PGPORT by hand. */ + PostPortName = (short) atoi(optarg); + break; + case 'S': + /* + * Start in 'S'ilent mode (disassociate from controlling tty). + * You may also think of this as 'S'ysV mode since it's most + * badly needed on SysV-derived systems like SVR4 and HP-UX. + */ + silentflag = 1; + break; + case 's': + /* + * In the event that some backend dumps core, + * send SIGSTOP, rather than SIGUSR1, to all + * its peers. This lets the wily post_hacker + * collect core dumps from everyone. + */ + SendStop = 1; + break; + default: + /* usage() never returns */ + usage(progname); + break; + } } if (PostPortName == -1) - PostPortName = pq_getport(); + PostPortName = pq_getport(); - IsPostmaster = true; - - if (!DataDir) - DataDir = GetPGData(); + checkDataDir(DataDir, &DataDirOK); /* issues error messages */ + if (!DataDirOK) { + fprintf(stderr, "No data directory -- can't proceed.\n"); + exit(2); + } - /* - * check whether the data directory exists. Passing this test doesn't - * gaurantee we are accessing the right data base but is a first barrier - * to site administrators who starts up the postmaster without realizing - * it cannot access the data base. - */ - checkDataDir(); - if (!Execfile[0] && FindBackend(Execfile, argv[0]) < 0) { - fprintf(stderr, "%s: could not find backend to execute...\n", - argv[0]); - exit(1); + fprintf(stderr, "%s: could not find backend to execute...\n", + argv[0]); + exit(1); } @@ -321,9 +375,9 @@ PostmasterMain(int argc, char *argv[]) status = StreamServerPort(hostName, PostPortName, &ServerSock); if (status != STATUS_OK) { - fprintf(stderr, "%s: cannot create stream port\n", - progname); - exit(1); + fprintf(stderr, "%s: cannot create stream port\n", + progname); + exit(1); } /* set up shared memory and semaphores */ @@ -338,7 +392,7 @@ PostmasterMain(int argc, char *argv[]) PortList = DLNewList(); if (silentflag) - pmdaemonize(); + pmdaemonize(); signal(SIGINT, pmdie); #ifndef WIN32 @@ -363,12 +417,12 @@ pmdaemonize(void) int i; if (fork()) - exit(0); + exit(0); if (setsid() < 0) { - fprintf(stderr, "%s: ", progname); - perror("cannot disassociate from controlling TTY"); - exit(1); + fprintf(stderr, "%s: ", progname); + perror("cannot disassociate from controlling TTY"); + exit(1); } i = open(NULL_DEV, O_RDWR); (void) dup2(i, 0); @@ -398,9 +452,9 @@ usage(const char *progname) int ServerLoop(void) { - int serverFd = ServerSock; - fd_set rmask, basemask; - int nSockets, nSelected, status, newFd; + int serverFd = ServerSock; + fd_set rmask, basemask; + int nSockets, nSelected, status, newFd; Dlelem *next, *curr; /* int orgsigmask = sigblock(0); */ sigset_t oldsigmask, newsigmask; @@ -413,104 +467,104 @@ ServerLoop(void) sigemptyset(&newsigmask); sigaddset(&newsigmask,SIGCHLD); for (;;) { -/* sigsetmask(orgsigmask); */ - sigprocmask(SIG_SETMASK,&oldsigmask,0); - newFd = -1; - memmove((char *) &rmask, (char *) &basemask, sizeof(fd_set)); - if ((nSelected = select(nSockets, &rmask, - (fd_set *) NULL, - (fd_set *) NULL, - (struct timeval *) NULL)) < 0) { - if (errno == EINTR) - continue; - fprintf(stderr, "%s: ServerLoop: select failed\n", - progname); - return(STATUS_ERROR); +/* sigsetmask(orgsigmask); */ + sigprocmask(SIG_SETMASK,&oldsigmask,0); + newFd = -1; + memmove((char *) &rmask, (char *) &basemask, sizeof(fd_set)); + if ((nSelected = select(nSockets, &rmask, + (fd_set *) NULL, + (fd_set *) NULL, + (struct timeval *) NULL)) < 0) { + if (errno == EINTR) + continue; + fprintf(stderr, "%s: ServerLoop: select failed\n", + progname); + return(STATUS_ERROR); } - /* [TRH] - * To avoid race conditions, block SIGCHLD signals while we are - * handling the request. (both reaper() and ConnCreate() - * manipulate the BackEnd list, and reaper() calls free() which is - * usually non-reentrant.) - */ - sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask); -/* sigblock(sigmask(SIGCHLD)); */ /* XXX[TRH] portability */ - if (DebugLvl > 1) { - fprintf(stderr, "%s: ServerLoop: %d sockets pending\n", - progname, nSelected); - } - - /* new connection pending on our well-known port's socket */ - if (FD_ISSET(ServerSock, &rmask)) { - /* - * connect and make an addition to PortList. If - * the connection dies and we notice it, just forget - * about the whole thing. - */ - if (ConnCreate(serverFd, &newFd) == STATUS_OK) { - if (newFd >= nSockets) - nSockets = newFd + 1; - FD_SET(newFd, &rmask); - FD_SET(newFd, &basemask); - if (DebugLvl) - fprintf(stderr, "%s: ServerLoop: connect on %d\n", - progname, newFd); - } - --nSelected; - FD_CLR(ServerSock, &rmask); - } + /* [TRH] + * To avoid race conditions, block SIGCHLD signals while we are + * handling the request. (both reaper() and ConnCreate() + * manipulate the BackEnd list, and reaper() calls free() which is + * usually non-reentrant.) + */ + sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask); +/* sigblock(sigmask(SIGCHLD)); */ /* XXX[TRH] portability */ + if (DebugLvl > 1) { + fprintf(stderr, "%s: ServerLoop: %d sockets pending\n", + progname, nSelected); + } + + /* new connection pending on our well-known port's socket */ + if (FD_ISSET(ServerSock, &rmask)) { + /* + * connect and make an addition to PortList. If + * the connection dies and we notice it, just forget + * about the whole thing. + */ + if (ConnCreate(serverFd, &newFd) == STATUS_OK) { + if (newFd >= nSockets) + nSockets = newFd + 1; + FD_SET(newFd, &rmask); + FD_SET(newFd, &basemask); + if (DebugLvl) + fprintf(stderr, "%s: ServerLoop: connect on %d\n", + progname, newFd); + } + --nSelected; + FD_CLR(ServerSock, &rmask); + } - if (DebugLvl > 1) { - fprintf(stderr, "%s: ServerLoop:\tnSelected=%d\n", - progname, nSelected); - curr = DLGetHead(PortList); - while (curr) { - Port *port = DLE_VAL(curr); - - fprintf(stderr, "%s: ServerLoop:\t\tport %d%s pending\n", - progname, port->sock, - FD_ISSET(port->sock, &rmask) - ? "" : - " not"); - curr = DLGetSucc(curr); - } - } - - curr = DLGetHead(PortList); - - while (curr) { - Port *port = (Port*)DLE_VAL(curr); - int lastbytes = port->nBytes; - - if (FD_ISSET(port->sock, &rmask) && port->sock != newFd) { - if (DebugLvl > 1) - fprintf(stderr, "%s: ServerLoop:\t\thandling %d\n", - progname, port->sock); - --nSelected; - - /* - * Read the incoming packet into its packet buffer. - * Read the connection id out of the packet so we - * know who the packet is from. - */ - status = PacketReceive(port, &port->buf, NON_BLOCKING); - switch (status) { - case STATUS_OK: { + if (DebugLvl > 1) { + fprintf(stderr, "%s: ServerLoop:\tnSelected=%d\n", + progname, nSelected); + curr = DLGetHead(PortList); + while (curr) { + Port *port = DLE_VAL(curr); + + fprintf(stderr, "%s: ServerLoop:\t\tport %d%s pending\n", + progname, port->sock, + FD_ISSET(port->sock, &rmask) + ? "" : + " not"); + curr = DLGetSucc(curr); + } + } + + curr = DLGetHead(PortList); + + while (curr) { + Port *port = (Port*)DLE_VAL(curr); + int lastbytes = port->nBytes; + + if (FD_ISSET(port->sock, &rmask) && port->sock != newFd) { + if (DebugLvl > 1) + fprintf(stderr, "%s: ServerLoop:\t\thandling %d\n", + progname, port->sock); + --nSelected; + + /* + * Read the incoming packet into its packet buffer. + * Read the connection id out of the packet so we + * know who the packet is from. + */ + status = PacketReceive(port, &port->buf, NON_BLOCKING); + switch (status) { + case STATUS_OK: { int CSstatus; /* Completion status of ConnStartup */ char errormsg[200]; /* error msg from ConnStartup */ - ConnStartup(port, &CSstatus, errormsg, sizeof(errormsg)); + ConnStartup(port, &CSstatus, errormsg, sizeof(errormsg)); if (CSstatus == STATUS_ERROR) send_error_reply(port, errormsg); - ActiveBackends = TRUE; + ActiveBackends = TRUE; } - /*FALLTHROUGH*/ - case STATUS_INVALID: - if (DebugLvl) - fprintf(stderr, "%s: ServerLoop:\t\tdone with %d\n", - progname, port->sock); - break; + /*FALLTHROUGH*/ + case STATUS_INVALID: + if (DebugLvl) + fprintf(stderr, "%s: ServerLoop:\t\tdone with %d\n", + progname, port->sock); + break; case STATUS_BAD_PACKET: /* * This is a bogus client, kill the connection @@ -519,41 +573,41 @@ ServerLoop(void) if (DebugLvl) fprintf(stderr, "%s: ServerLoop:\t\tbad packet format (reported packet size of %d read on port %d\n", progname, port->nBytes, port->sock); break; - case STATUS_NOT_DONE: - if (DebugLvl) - fprintf(stderr, "%s: ServerLoop:\t\tpartial packet (%d bytes actually read) on %d\n", - progname, port->nBytes, port->sock); - /* - * If we've received at least a PacketHdr's worth of data - * and we're still receiving data each time we read, we're - * ok. If the client gives us less than a PacketHdr at - * the beginning, just kill the connection and forget - * about the whole thing. - */ - if (lastbytes < port->nBytes) { - if (DebugLvl) - fprintf(stderr, "%s: ServerLoop:\t\tpartial packet on %d ok\n", - progname, port->sock); - curr = DLGetSucc(curr); - continue; - } - break; - case STATUS_ERROR: /* system call error - die */ - fprintf(stderr, "%s: ServerLoop:\t\terror receiving packet\n", - progname); - return(STATUS_ERROR); - } - FD_CLR(port->sock, &basemask); - StreamClose(port->sock); - next = DLGetSucc(curr); - DLRemove(curr); - DLFreeElem(curr); - curr = next; + case STATUS_NOT_DONE: + if (DebugLvl) + fprintf(stderr, "%s: ServerLoop:\t\tpartial packet (%d bytes actually read) on %d\n", + progname, port->nBytes, port->sock); + /* + * If we've received at least a PacketHdr's worth of data + * and we're still receiving data each time we read, we're + * ok. If the client gives us less than a PacketHdr at + * the beginning, just kill the connection and forget + * about the whole thing. + */ + if (lastbytes < port->nBytes) { + if (DebugLvl) + fprintf(stderr, "%s: ServerLoop:\t\tpartial packet on %d ok\n", + progname, port->sock); + curr = DLGetSucc(curr); + continue; + } + break; + case STATUS_ERROR: /* system call error - die */ + fprintf(stderr, "%s: ServerLoop:\t\terror receiving packet\n", + progname); + return(STATUS_ERROR); + } + FD_CLR(port->sock, &basemask); + StreamClose(port->sock); + next = DLGetSucc(curr); + DLRemove(curr); + DLFreeElem(curr); + curr = next; continue; - } - curr = DLGetSucc(curr); - } - Assert(nSelected == 0); + } + curr = DLGetSucc(curr); + } + Assert(nSelected == 0); } } @@ -574,7 +628,7 @@ ConnStartup(Port *port, int *status, { MsgType msgType; char namebuf[NAMEDATALEN + 1]; - int pid; + int pid; PacketBuf *p; StartupInfo sp; char *tmp; @@ -708,23 +762,23 @@ send_error_reply(Port *port, const char *errormsg) static int ConnCreate(int serverFd, int *newFdP) { - int status; - Port *port; + int status; + Port *port; if (!(port = (Port *) calloc(1, sizeof(Port)))) { - fprintf(stderr, "%s: ConnCreate: malloc failed\n", - progname); - ExitPostmaster(1); + fprintf(stderr, "%s: ConnCreate: malloc failed\n", + progname); + ExitPostmaster(1); } if ((status = StreamConnection(serverFd, port)) != STATUS_OK) { - StreamClose(port->sock); - free(port); + StreamClose(port->sock); + free(port); } else { - DLAddHead(PortList, DLNewElem(port)); - *newFdP = port->sock; + DLAddHead(PortList, DLNewElem(port)); + *newFdP = port->sock; } return (status); @@ -736,7 +790,7 @@ ConnCreate(int serverFd, int *newFdP) static void reset_shared(short port) { - IPCKey key; + IPCKey key; key = SystemPortAddressCreateIPCKey((SystemPortAddress) port); CreateSharedMemoryAndSemaphores(key); @@ -758,15 +812,15 @@ pmdie(SIGNAL_ARGS) static void reaper(SIGNAL_ARGS) { - int status; /* backend exit status */ - int pid; /* process id of dead backend */ + int status; /* backend exit status */ + int pid; /* process id of dead backend */ if (DebugLvl) - fprintf(stderr, "%s: reaping dead processes...\n", - progname); + fprintf(stderr, "%s: reaping dead processes...\n", + progname); #ifndef WIN32 while((pid = waitpid(-1, &status, WNOHANG)) > 0) - CleanupProc(pid, status); + CleanupProc(pid, status); #endif /* WIN32 */ } @@ -779,15 +833,15 @@ reaper(SIGNAL_ARGS) */ static void CleanupProc(int pid, - int exitstatus) /* child's exit status. */ + int exitstatus) /* child's exit status. */ { Dlelem *prev, *curr; - Backend *bp; - int sig; + Backend *bp; + int sig; if (DebugLvl) { - fprintf(stderr, "%s: CleanupProc: pid %d exited with status %d\n", - progname, pid, exitstatus); + fprintf(stderr, "%s: CleanupProc: pid %d exited with status %d\n", + progname, pid, exitstatus); } /* * ------------------------- @@ -798,57 +852,57 @@ CleanupProc(int pid, * ------------------------- */ if (!exitstatus) { - curr = DLGetHead(BackendList); - while (curr) { - bp = (Backend*)DLE_VAL(curr); - if (bp->pid == pid) { - DLRemove(curr); - DLFreeElem(curr); - break; - } - curr = DLGetSucc(curr); - } - - ProcRemove(pid); - - return; + curr = DLGetHead(BackendList); + while (curr) { + bp = (Backend*)DLE_VAL(curr); + if (bp->pid == pid) { + DLRemove(curr); + 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 sez exit without exitpg - * and let the user know what's going on. ProcSemaphoreKill() - * cleans up the backends semaphore. If SendStop is set (-s on - * the command line), then we send a SIGSTOP so that we can - * collect core dumps from all backends by hand. - * ----------------- - */ + bp = (Backend*)DLE_VAL(curr); + + /* + * ----------------- + * SIGUSR1 is the special signal that sez exit without exitpg + * and let the user know what's going on. ProcSemaphoreKill() + * cleans up the backends semaphore. If SendStop is set (-s on + * the command line), then we send a SIGSTOP so that we can + * collect core dumps from all backends by hand. + * ----------------- + */ #ifndef WIN32 - 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); - (void) kill(bp->pid, sig); - } + 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); + (void) kill(bp->pid, sig); + } #endif /* WIN32 */ - ProcRemove(bp->pid); - - prev = DLGetPred(curr); - DLRemove(curr); - DLFreeElem(curr); - if (!prev) { /* removed head */ - curr = DLGetHead(BackendList); - continue; - } - curr = DLGetSucc(curr); + ProcRemove(bp->pid); + + prev = DLGetPred(curr); + DLRemove(curr); + DLFreeElem(curr); + if (!prev) { /* removed head */ + curr = DLGetHead(BackendList); + continue; + } + curr = DLGetSucc(curr); } /* * ------------- @@ -865,11 +919,11 @@ CleanupProc(int pid, * ---------------- */ if (ActiveBackends == TRUE && Reinit) { - if (DebugLvl) - fprintf(stderr, "%s: CleanupProc: reinitializing shared memory and semaphores\n", - progname); - quasi_exitpg(); - reset_shared(PostPortName); + if (DebugLvl) + fprintf(stderr, "%s: CleanupProc: reinitializing shared memory and semaphores\n", + progname); + quasi_exitpg(); + reset_shared(PostPortName); } } @@ -877,20 +931,20 @@ CleanupProc(int pid, * BackendStartup -- start backend process * * returns: STATUS_ERROR if the fork/exec failed, STATUS_OK - * otherwise. + * otherwise. * */ int BackendStartup(StartupInfo *packet, /* client's startup packet */ - Port *port, - int *pidPtr) + Port *port, + int *pidPtr) { Backend* bn; /* for backend cleanup */ - int pid, i; - static char envEntry[4][2 * ARGV_SIZE]; + int pid, i; + static char envEntry[4][2 * ARGV_SIZE]; for (i = 0; i < 4; ++i) { - memset(envEntry[i], 0, 2*ARGV_SIZE); + memset(envEntry[i], 0, 2*ARGV_SIZE); } /* * Set up the necessary environment variables for the backend @@ -903,50 +957,50 @@ BackendStartup(StartupInfo *packet, /* client's startup packet */ sprintf(envEntry[2], "PG_USER=%s", packet->user); putenv(envEntry[2]); if (!getenv("PGDATA")) { - sprintf(envEntry[3], "PGDATA=%s", DataDir); - putenv(envEntry[3]); + sprintf(envEntry[3], "PGDATA=%s", DataDir); + putenv(envEntry[3]); } 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"); + 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"); } #ifndef WIN32 - if ((pid = FORK()) == 0) { /* child */ - if (DoExec(packet, port->sock)) - fprintf(stderr, "%s child[%d]: BackendStartup: execv failed\n", - progname, pid); - /* use _exit to keep from double-flushing stdio */ - _exit(1); + if ((pid = FORK()) == 0) { /* child */ + if (DoExec(packet, port->sock)) + fprintf(stderr, "%s child[%d]: BackendStartup: execv failed\n", + progname, pid); + /* use _exit to keep from double-flushing stdio */ + _exit(1); } /* in parent */ if (pid < 0) { - fprintf(stderr, "%s: BackendStartup: fork failed\n", - progname); - return(STATUS_ERROR); + fprintf(stderr, "%s: BackendStartup: fork failed\n", + progname); + return(STATUS_ERROR); } #else pid = DoExec(packet, port->sock); if (pid == FALSE) { - fprintf(stderr, "%s: BackendStartup: CreateProcess failed\n", - progname); - return(STATUS_ERROR); + fprintf(stderr, "%s: BackendStartup: CreateProcess failed\n", + progname); + return(STATUS_ERROR); } #endif /* WIN32 */ if (DebugLvl) - fprintf(stderr, "%s: BackendStartup: pid %d user %s db %s socket %d\n", - progname, pid, packet->user, - (packet->database[0] == '\0' ? packet->user : packet->database), - port->sock); + fprintf(stderr, "%s: BackendStartup: pid %d user %s db %s socket %d\n", + progname, pid, packet->user, + (packet->database[0] == '\0' ? packet->user : packet->database), + port->sock); /* adjust backend counter */ /* XXX Don't know why this is done, but for now backend needs it */ @@ -957,16 +1011,16 @@ BackendStartup(StartupInfo *packet, /* client's startup packet */ * list of backends. */ if (!(bn = (Backend *) calloc(1, sizeof (Backend)))) { - fprintf(stderr, "%s: BackendStartup: malloc failed\n", - progname); - ExitPostmaster(1); + fprintf(stderr, "%s: BackendStartup: malloc failed\n", + progname); + ExitPostmaster(1); } bn->pid = pid; DLAddHead(BackendList,DLNewElem(bn)); if (MultiplexedBackends) - MultiplexedBackendPort++; + MultiplexedBackendPort++; *pidPtr = pid; @@ -986,17 +1040,17 @@ BackendStartup(StartupInfo *packet, /* client's startup packet */ static void split_opts(char **argv, int *argcp, char *s) { - int i = *argcp; + int i = *argcp; while (s && *s) { - while (isspace(*s)) - ++s; - if (*s) - argv[i++] = s; - while (*s && !isspace(*s)) - ++s; - if (isspace(*s)) - *s++ = '\0'; + while (isspace(*s)) + ++s; + if (*s) + argv[i++] = s; + while (*s && !isspace(*s)) + ++s; + if (isspace(*s)) + *s++ = '\0'; } *argcp = i; } @@ -1010,26 +1064,26 @@ split_opts(char **argv, int *argcp, char *s) * fork() because we don't have vfork(), then we don't really care.) * * returns: - * Shouldn't return at all. - * If execv() fails, return status. + * Shouldn't return at all. + * If execv() fails, return status. */ static int DoExec(StartupInfo *packet, int portFd) { - char execbuf[MAXPATHLEN]; - char portbuf[ARGV_SIZE]; + char execbuf[MAXPATHLEN]; + char portbuf[ARGV_SIZE]; char mbbuf[ARGV_SIZE]; - char debugbuf[ARGV_SIZE]; - char ttybuf[ARGV_SIZE + 1]; - char argbuf[(2 * ARGV_SIZE) + 1]; + char debugbuf[ARGV_SIZE]; + char ttybuf[ARGV_SIZE + 1]; + char argbuf[(2 * ARGV_SIZE) + 1]; /* * each argument takes at least three chars, so we can't * have more than ARGV_SIZE arguments in (2 * ARGV_SIZE) * chars (i.e., packet->options plus ExtraOptions)... */ - char *av[ARGV_SIZE]; - char dbbuf[ARGV_SIZE + 1]; - int ac = 0; + char *av[ARGV_SIZE]; + char dbbuf[ARGV_SIZE + 1]; + int ac = 0; int i; #if defined(WIN32) char win32_args[(2 * ARGV_SIZE) + 1]; @@ -1054,16 +1108,16 @@ DoExec(StartupInfo *packet, int portFd) */ if (DebugLvl > 1) { - (void) sprintf(debugbuf, "-d%d", DebugLvl - 1); - av[ac++] = debugbuf; + (void) sprintf(debugbuf, "-d%d", DebugLvl - 1); + av[ac++] = debugbuf; } else - av[ac++] = "-Q"; + av[ac++] = "-Q"; /* Pass the requested debugging output file */ if (packet->tty[0]) { - (void) strncpy(ttybuf, packet->tty, ARGV_SIZE); - av[ac++] = "-o"; + (void) strncpy(ttybuf, packet->tty, ARGV_SIZE); + av[ac++] = "-o"; #if defined(WIN32) /* BIG HACK - The front end is passing "/dev/null" here which ** causes new backends to fail. So, as a very special case, @@ -1092,20 +1146,20 @@ DoExec(StartupInfo *packet, int portFd) split_opts(av, &ac, argbuf); if (packet->database[0]) - (void) strncpy(dbbuf, packet->database, ARGV_SIZE); + (void) strncpy(dbbuf, packet->database, ARGV_SIZE); else - (void) strncpy(dbbuf, packet->user, NAMEDATALEN); + (void) strncpy(dbbuf, packet->user, NAMEDATALEN); dbbuf[ARGV_SIZE] = '\0'; av[ac++] = dbbuf; av[ac] = (char *) NULL; if (DebugLvl > 1) { - fprintf(stderr, "%s child[%ld]: execv(", - progname, (long)getpid()); - for (i = 0; i < ac; ++i) - fprintf(stderr, "%s, ", av[i]); - fprintf(stderr, ")\n"); + fprintf(stderr, "%s child[%ld]: execv(", + progname, (long)getpid()); + for (i = 0; i < ac; ++i) + fprintf(stderr, "%s, ", av[i]); + fprintf(stderr, ")\n"); } #ifndef WIN32 @@ -1156,7 +1210,7 @@ ExitPostmaster(int status) * should the backends all be killed? probably not. */ if (ServerSock != INVALID_SOCK) - close(ServerSock); + close(ServerSock); exitpg(status); } @@ -1166,50 +1220,17 @@ dumpstatus(SIGNAL_ARGS) Dlelem *curr = DLGetHead(PortList); while (curr) { - Port *port = DLE_VAL(curr); - - fprintf(stderr, "%s: dumpstatus:\n", progname); - fprintf(stderr, "\tsock %d: nBytes=%d, laddr=0x%lx, raddr=0x%lx\n", - port->sock, port->nBytes, - (long int) port->laddr.sin_addr.s_addr, - (long int) port->raddr.sin_addr.s_addr); - curr = DLGetSucc(curr); + Port *port = DLE_VAL(curr); + + fprintf(stderr, "%s: dumpstatus:\n", progname); + fprintf(stderr, "\tsock %d: nBytes=%d, laddr=0x%lx, raddr=0x%lx\n", + port->sock, port->nBytes, + (long int) port->laddr.sin_addr.s_addr, + (long int) port->raddr.sin_addr.s_addr); + curr = DLGetSucc(curr); } } -static void -checkDataDir(void) -{ - char path[MAXPATHLEN]; - FILE *fp; - - sprintf(path, "%s%cbase%ctemplate1%cpg_class", DataDir, SEP_CHAR, SEP_CHAR, - SEP_CHAR); - if ((fp=fopen(path, "r")) == NULL) { - fprintf(stderr, "%s does not find the database. Expected to find it " - "in the PGDATA directory \"%s\", but unable to open file " - "with pathname \"%s\".\n", - progname, DataDir, path); - exit(2); - } - fclose(fp); -#ifndef WIN32 - { - char *reason; /* reason ValidatePgVersion failed. NULL if didn't */ - ValidatePgVersion(DataDir, &reason); - if (reason) { - fprintf(stderr, - "Database system in directory %s " - "is not compatible with this version of " - "Postgres, or we are unable to read the PG_VERSION file. " - "Explanation from ValidatePgVersion: %s\n", - DataDir, reason); - free(reason); - exit(2); - } - } -#endif /* WIN32 */ -} |