1 /*-------------------------------------------------------------------------
4 * This program acts as a clearing house for requests to the
5 * POSTGRES system. Frontend programs send a startup message
6 * to the Postmaster and the postmaster uses the info in the
7 * message to setup a backend process.
9 * Copyright (c) 1994, Regents of the University of California
13 * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.98 1998/11/29 01:51:56 tgl Exp $
18 * The Postmaster sets up a few shared memory data structures
19 * for the backends. It should at the very least initialize the
23 * The Postmaster shares memory with the backends and will have to lock
24 * the shared memory it accesses. The Postmaster should never block
25 * on messages from clients.
28 * The Postmaster cleans up after backends if they have an emergency
29 * exit and/or core dump.
33 *-------------------------------------------------------------------------
35 /* moved here to prevent double define */
36 #include <sys/param.h> /* for MAXHOSTNAMELEN on most */
38 #include <netdb.h> /* for MAXHOSTNAMELEN on some */
41 #ifndef MAXHOSTNAMELEN
42 #define MAXHOSTNAMELEN 256
52 #if !defined(NO_UNISTD_H)
54 #endif /* !NO_UNISTD_H */
57 #include <sys/types.h> /* for fd_set stuff */
58 #include <sys/stat.h> /* for umask */
60 #include <sys/socket.h>
72 #ifdef HAVE_SYS_SELECT_H
73 #include <sys/select.h>
76 #include "storage/ipc.h"
77 #include "libpq/libpq.h"
78 #include "libpq/auth.h"
79 #include "libpq/pqcomm.h"
80 #include "libpq/pqsignal.h"
81 #include "libpq/crypt.h"
82 #include "miscadmin.h"
84 #include "lib/dllist.h"
85 #include "tcop/tcopprot.h"
86 #include "commands/async.h"
87 #include "nodes/nodes.h"
88 #include "utils/mcxt.h"
89 #include "storage/proc.h"
90 #include "utils/elog.h"
91 #ifndef HAVE_GETHOSTNAME
92 #include "port-protos.h" /* For gethostname() */
94 #include "storage/fd.h"
95 #include "utils/trace.h"
98 #define MAXINT INT_MAX
101 #define INVALID_SOCK (-1)
105 * Max time in seconds for socket to linger (close() to block) waiting
106 * for frontend to retrieve its message from us.
110 * Info for garbage collection. Whenever a process dies, the Postmaster
111 * cleans up after it. Currently, NO information is required for cleanup,
112 * but I left this structure around in case that changed.
116 int pid
; /* process id of backend */
117 long cancel_key
; /* cancel key for cancels for this backend */
120 Port
*MyBackendPort
= NULL
;
122 /* list of active backends. For garbage collection only now. */
124 static Dllist
*BackendList
;
126 /* list of ports associated with still open, but incomplete connections */
127 static Dllist
*PortList
;
129 static short PostPortName
= -1;
130 static short ActiveBackends
= FALSE
;
133 * This is a boolean indicating that there is at least one backend that
134 * is accessing the current shared memory and semaphores. Between the
135 * time that we start up, or throw away shared memory segments and start
136 * over, and the time we generate the next backend (because we received a
137 * connection request), it is false. Other times, it is true.
139 static short shmem_seq
= 0;
142 * This is a sequence number that indicates how many times we've had to
143 * throw away the shared memory and start over because we doubted its
144 * integrity. It starts off at zero and is incremented every time we
145 * start over. We use this to ensure that we use a new IPC shared memory
146 * key for the new shared memory segment in case the old segment isn't
149 * The sequence actually cycles back to 0 after 9, so pathologically there
150 * could be an IPC failure if 10 sets of backends are all stuck and won't
151 * release IPC resources.
154 static IpcMemoryKey ipc_key
;
157 * This is the base IPC shared memory key. Other keys are generated by
162 static int NextBackendId
= MAXINT
; /* XXX why? */
163 static char *progname
= (char *) NULL
;
164 static char **real_argv
;
165 static int real_argc
;
170 static char Execfile
[MAXPATHLEN
] = "";
172 static int ServerSock_INET
= INVALID_SOCK
; /* stream socket server */
173 static int ServerSock_UNIX
= INVALID_SOCK
; /* stream socket server */
176 * Set by the -o option
178 static char ExtraOptions
[ARGV_SIZE
] = "";
181 * These globals control the behavior of the postmaster in case some
182 * backend dumps core. Normally, it kills all peers of the dead backend
183 * and reinitializes shared memory. By specifying -s or -n, we can have
184 * the postmaster stop (rather than kill) peers and not reinitialize
185 * shared data structures.
187 static bool Reinit
= true;
188 static int SendStop
= false;
190 static bool NetServer
= false; /* if not zero, postmaster listen for
191 * non-local connections */
195 * GH: For !HAVE_SIGPROCMASK (NEXTSTEP), TRH implemented an
196 * alternative interface.
198 #ifdef HAVE_SIGPROCMASK
199 static sigset_t oldsigmask
,
203 static int orgsigmask
= sigblock(0);
208 * State for assigning random salts and cancel keys.
209 * Also, the global MyCancelKey passes the cancel key assigned to a given
210 * backend from the postmaster to that backend (via fork).
213 static unsigned int random_seed
= 0;
221 * postmaster.c - function prototypes
223 static void pmdaemonize(void);
224 static Port
*ConnCreate(int serverFd
);
225 static void reset_shared(short port
);
226 static void pmdie(SIGNAL_ARGS
);
227 static void reaper(SIGNAL_ARGS
);
228 static void dumpstatus(SIGNAL_ARGS
);
229 static void CleanupProc(int pid
, int exitstatus
);
230 static int DoBackend(Port
*port
);
231 static void ExitPostmaster(int status
);
232 static void usage(const char *);
233 static int ServerLoop(void);
234 static int BackendStartup(Port
*port
);
235 static int readStartupPacket(void *arg
, PacketLen len
, void *pkt
);
236 static int processCancelRequest(Port
*port
, PacketLen len
, void *pkt
);
237 static int initMasks(fd_set
*rmask
, fd_set
*wmask
);
238 static long PostmasterRandom(void);
239 static void RandomSalt(char *salt
);
240 static void SignalChildren(SIGNAL_ARGS
);
243 void GetCharSetByHost(char *, int, char *);
247 #ifdef USE_ASSERT_CHECKING
248 int assert_enabled
= 1;
253 checkDataDir(const char *DataDir
, bool *DataDirOK
)
257 fprintf(stderr
, "%s does not know where to find the database system "
258 "data. You must specify the directory that contains the "
259 "database system either by specifying the -D invocation "
260 "option or by setting the PGDATA environment variable.\n\n",
266 char path
[MAXPATHLEN
];
269 sprintf(path
, "%s%cbase%ctemplate1%cpg_class",
270 DataDir
, SEP_CHAR
, SEP_CHAR
, SEP_CHAR
);
271 fp
= AllocateFile(path
, "r");
274 fprintf(stderr
, "%s does not find the database system. "
275 "Expected to find it "
276 "in the PGDATA directory \"%s\", but unable to open file "
277 "with pathname \"%s\".\n\n",
278 progname
, DataDir
, path
);
285 /* reason ValidatePgVersion failed. NULL if didn't */
289 ValidatePgVersion(DataDir
, &reason
);
293 "Database system in directory %s "
294 "is not compatible with this version of "
295 "Postgres, or we are unable to read the "
297 "Explanation from ValidatePgVersion: %s\n\n",
309 PostmasterMain(int argc
, char *argv
[])
311 extern int NBuffers
; /* from buffer/bufmgr.c */
316 bool DataDirOK
; /* We have a usable PGDATA value */
317 char hostbuf
[MAXHOSTNAMELEN
];
321 * We need three params so we can display status. If we don't get
322 * them from the user, let's make them ourselves.
329 for (i
= 0; i
< argc
; i
++)
330 new_argv
[i
] = argv
[i
];
335 if (!Execfile
[0] && FindExec(Execfile
, argv
[0], "postmaster") < 0)
337 fprintf(stderr
, "%s: could not find postmaster to execute...\n",
341 new_argv
[0] = Execfile
;
343 execv(new_argv
[0], new_argv
);
345 /* How did we get here, error! */
347 fprintf(stderr
, "PostmasterMain execv failed on %s\n", argv
[0]);
356 * don't process any dummy args we placed at the end for status
359 for (nonblank_argc
= argc
; nonblank_argc
> 0; nonblank_argc
--)
360 if (argv
[nonblank_argc
- 1] != NULL
&& argv
[nonblank_argc
- 1][0] != '\0')
364 * for security, no dir or file created can be group or other
367 umask((mode_t
) 0077);
369 if (!(hostName
= getenv("PGHOST")))
371 if (gethostname(hostbuf
, MAXHOSTNAMELEN
) < 0)
372 strcpy(hostbuf
, "localhost");
376 MyProcPid
= getpid();
377 DataDir
= getenv("PGDATA"); /* default value */
380 while ((opt
= getopt(nonblank_argc
, argv
, "A:a:B:b:D:dim:Mno:p:Ss")) != EOF
)
385 #ifndef USE_ASSERT_CHECKING
386 fprintf(stderr
, "Assert checking is not enabled\n");
390 * Pass this option also to each backend.
392 assert_enabled
= atoi(optarg
);
393 strcat(ExtraOptions
, " -A ");
394 strcat(ExtraOptions
, optarg
);
398 /* Can no longer set authentication method. */
403 * The number of buffers to create. Setting this option
404 * means we have to start each backend with a -B # to make
405 * sure they know how many buffers were allocated.
407 NBuffers
= atol(optarg
);
408 strcat(ExtraOptions
, " -B ");
409 strcat(ExtraOptions
, optarg
);
412 /* Set the backend executable file to use. */
413 if (!ValidateBinary(optarg
))
414 strcpy(Execfile
, optarg
);
417 fprintf(stderr
, "%s: invalid backend \"%s\"\n",
423 /* Set PGDATA from the command line. */
429 * Turn on debugging for the postmaster and the backend
430 * servers descended from it.
432 if ((optind
< nonblank_argc
) && *argv
[optind
] != '-')
434 DebugLvl
= atoi(argv
[optind
]);
439 pg_options
[TRACE_VERBOSE
] = DebugLvl
;
445 /* Multiplexed backends no longer supported. */
450 * ignore this flag. This may be passed in because the
451 * program was run as 'postgres -M' instead of
456 /* Don't reinit shared mem after abnormal exit */
462 * Other options to pass to the backend on the command
463 * line -- useful only for debugging.
465 strcat(ExtraOptions
, " ");
466 strcat(ExtraOptions
, optarg
);
469 /* Set PGPORT by hand. */
470 PostPortName
= (short) atoi(optarg
);
475 * Start in 'S'ilent mode (disassociate from controlling
476 * tty). You may also think of this as 'S'ysV mode since
477 * it's most badly needed on SysV-derived systems like
485 * In the event that some backend dumps core, send
486 * SIGSTOP, rather than SIGUSR1, to all its peers. This
487 * lets the wily post_hacker collect core dumps from
493 /* usage() never returns */
498 if (PostPortName
== -1)
499 PostPortName
= pq_getport();
501 checkDataDir(DataDir
, &DataDirOK
); /* issues error messages */
504 fprintf(stderr
, "No data directory -- can't proceed.\n");
508 if (!Execfile
[0] && FindExec(Execfile
, argv
[0], "postgres") < 0)
510 fprintf(stderr
, "%s: could not find backend to execute...\n",
517 status
= StreamServerPort(hostName
, PostPortName
, &ServerSock_INET
);
518 if (status
!= STATUS_OK
)
520 fprintf(stderr
, "%s: cannot create INET stream port\n",
525 status
= StreamServerPort(NULL
, PostPortName
, &ServerSock_UNIX
);
526 if (status
!= STATUS_OK
)
528 fprintf(stderr
, "%s: cannot create UNIX stream port\n",
533 /* set up shared memory and semaphores */
534 EnableMemoryContext(TRUE
);
535 reset_shared(PostPortName
);
538 * Initialize the list of active backends. This list is only used for
539 * garbage collecting the backend processes.
541 BackendList
= DLNewList();
542 PortList
= DLNewList();
548 * Set up signal handlers for the postmaster process.
551 pqsignal(SIGHUP
, pmdie
); /* send SIGHUP, don't die */
552 pqsignal(SIGINT
, pmdie
); /* die */
553 pqsignal(SIGQUIT
, pmdie
); /* send SIGTERM and die */
554 pqsignal(SIGTERM
, pmdie
); /* send SIGTERM,SIGKILL and die */
555 pqsignal(SIGPIPE
, SIG_IGN
); /* ignored */
556 pqsignal(SIGUSR1
, pmdie
); /* send SIGUSR1 and die */
557 pqsignal(SIGUSR2
, pmdie
); /* send SIGUSR2, don't die */
558 pqsignal(SIGCHLD
, reaper
); /* handle child termination */
559 pqsignal(SIGTTIN
, SIG_IGN
); /* ignored */
560 pqsignal(SIGTTOU
, SIG_IGN
); /* ignored */
561 pqsignal(SIGWINCH
, dumpstatus
); /* dump port status */
563 status
= ServerLoop();
565 ExitPostmaster(status
!= STATUS_OK
);
566 return 0; /* not reached */
576 /* GH: If there's no setsid(), we hopefully don't need silent mode.
577 * Until there's a better solution.
582 fprintf(stderr
, "%s: ", progname
);
583 perror("cannot disassociate from controlling TTY");
587 i
= open(NULL_DEV
, O_RDWR
);
595 usage(const char *progname
)
597 fprintf(stderr
, "usage: %s [options]\n", progname
);
598 #ifdef USE_ASSERT_CHECKING
599 fprintf(stderr
, "\t-A [1|0]\tenable/disable runtime assert checking\n");
601 fprintf(stderr
, "\t-B nbufs\tset number of shared buffers\n");
602 fprintf(stderr
, "\t-D datadir\tset data directory\n");
603 fprintf(stderr
, "\t-S \t\tsilent mode (disassociate from tty)\n");
604 fprintf(stderr
, "\t-a system\tuse this authentication system\n");
605 fprintf(stderr
, "\t-b backend\tuse a specific backend server executable\n");
606 fprintf(stderr
, "\t-d [1|2|3]\tset debugging level\n");
607 fprintf(stderr
, "\t-i \t\tlisten on TCP/IP sockets as well as Unix domain socket\n");
608 fprintf(stderr
, "\t-n \t\tdon't reinitialize shared memory after abnormal exit\n");
609 fprintf(stderr
, "\t-o option\tpass 'option' to each backend servers\n");
610 fprintf(stderr
, "\t-p port\tspecify port for postmaster to listen on\n");
611 fprintf(stderr
, "\t-s \t\tsend SIGSTOP to all backend servers if one dies\n");
626 gettimeofday(&now
, &tz
);
628 nSockets
= initMasks(&readmask
, &writemask
);
630 #ifdef HAVE_SIGPROCMASK
631 sigprocmask(0, NULL
, &oldsigmask
);
632 sigemptyset(&newsigmask
);
633 sigaddset(&newsigmask
, SIGCHLD
);
642 #ifdef HAVE_SIGPROCMASK
643 sigprocmask(SIG_SETMASK
, &oldsigmask
, 0);
645 sigsetmask(orgsigmask
);
648 memmove((char *) &rmask
, (char *) &readmask
, sizeof(fd_set
));
649 memmove((char *) &wmask
, (char *) &writemask
, sizeof(fd_set
));
650 if (select(nSockets
, &rmask
, &wmask
, (fd_set
*) NULL
,
651 (struct timeval
*) NULL
) < 0)
655 fprintf(stderr
, "%s: ServerLoop: select failed\n",
661 * Select a random seed at the time of first receiving a request.
663 while (random_seed
== 0)
665 gettimeofday(&later
, &tz
);
668 * We are not sure how much precision is in tv_usec, so we
669 * swap the nibbles of 'later' and XOR them with 'now'. On the
670 * off chance that the result is 0, we loop until it isn't.
672 random_seed
= now
.tv_usec
^
673 ((later
.tv_usec
<< 16) |
674 ((later
.tv_usec
>> 16) & 0xffff));
678 * [TRH] To avoid race conditions, block SIGCHLD signals while we
679 * are handling the request. (both reaper() and ConnCreate()
680 * manipulate the BackEnd list, and reaper() calls free() which is
681 * usually non-reentrant.)
683 #ifdef HAVE_SIGPROCMASK
684 sigprocmask(SIG_BLOCK
, &newsigmask
, &oldsigmask
);
686 sigblock(sigmask(SIGCHLD
)); /* XXX[TRH] portability */
689 /* new connection pending on our well-known port's socket */
691 if (ServerSock_UNIX
!= INVALID_SOCK
&&
692 FD_ISSET(ServerSock_UNIX
, &rmask
) &&
693 (port
= ConnCreate(ServerSock_UNIX
)) != NULL
)
694 PacketReceiveSetup(&port
->pktInfo
,
698 if (ServerSock_INET
!= INVALID_SOCK
&&
699 FD_ISSET(ServerSock_INET
, &rmask
) &&
700 (port
= ConnCreate(ServerSock_INET
)) != NULL
)
701 PacketReceiveSetup(&port
->pktInfo
,
705 /* Build up new masks for select(). */
707 nSockets
= initMasks(&readmask
, &writemask
);
709 curr
= DLGetHead(PortList
);
713 Port
*port
= (Port
*) DLE_VAL(curr
);
714 int status
= STATUS_OK
;
717 if (FD_ISSET(port
->sock
, &rmask
))
720 fprintf(stderr
, "%s: ServerLoop:\t\thandling reading %d\n",
721 progname
, port
->sock
);
723 if (PacketReceiveFragment(&port
->pktInfo
, port
->sock
) != STATUS_OK
)
724 status
= STATUS_ERROR
;
727 if (FD_ISSET(port
->sock
, &wmask
))
730 fprintf(stderr
, "%s: ServerLoop:\t\thandling writing %d\n",
731 progname
, port
->sock
);
733 if (PacketSendFragment(&port
->pktInfo
, port
->sock
) != STATUS_OK
)
734 status
= STATUS_ERROR
;
737 /* Get this before the connection might be closed. */
739 next
= DLGetSucc(curr
);
742 * If there is no error and no outstanding data transfer going
743 * on, then the authentication handshake must be complete to
744 * the postmaster's satisfaction. So, start the backend.
747 if (status
== STATUS_OK
&& port
->pktInfo
.state
== Idle
)
751 * If the backend start fails then keep the connection
752 * open to report it. Otherwise, pretend there is an
753 * error to close the connection which will now be managed
757 if (BackendStartup(port
) != STATUS_OK
)
758 PacketSendError(&port
->pktInfo
,
759 "Backend startup failed");
761 status
= STATUS_ERROR
;
764 /* Close the connection if required. */
766 if (status
!= STATUS_OK
)
768 StreamClose(port
->sock
);
775 /* Set the masks for this connection. */
777 if (nSockets
<= port
->sock
)
778 nSockets
= port
->sock
+ 1;
780 if (port
->pktInfo
.state
== WritingPacket
)
781 FD_SET(port
->sock
, &writemask
);
783 FD_SET(port
->sock
, &readmask
);
793 * Initialise the read and write masks for select() for the well-known ports
794 * we are listening on. Return the number of sockets to listen on.
798 initMasks(fd_set
*rmask
, fd_set
*wmask
)
805 if (ServerSock_UNIX
!= INVALID_SOCK
)
807 FD_SET(ServerSock_UNIX
, rmask
);
809 if (ServerSock_UNIX
> nsocks
)
810 nsocks
= ServerSock_UNIX
;
813 if (ServerSock_INET
!= INVALID_SOCK
)
815 FD_SET(ServerSock_INET
, rmask
);
817 if (ServerSock_INET
> nsocks
)
818 nsocks
= ServerSock_INET
;
826 * Called when the startup packet has been read.
830 readStartupPacket(void *arg
, PacketLen len
, void *pkt
)
836 si
= (StartupPacket
*) pkt
;
839 * The first field is either a protocol version number or a special
843 port
->proto
= ntohl(si
->protoVersion
);
845 if (port
->proto
== CANCEL_REQUEST_CODE
)
846 return processCancelRequest(port
, len
, pkt
);
848 /* Could add additional special packet types here */
850 /* Check we can handle the protocol the frontend is using. */
852 if (PG_PROTOCOL_MAJOR(port
->proto
) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST
) ||
853 PG_PROTOCOL_MAJOR(port
->proto
) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST
) ||
854 (PG_PROTOCOL_MAJOR(port
->proto
) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST
) &&
855 PG_PROTOCOL_MINOR(port
->proto
) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST
)))
857 PacketSendError(&port
->pktInfo
, "Unsupported frontend protocol.");
858 return STATUS_OK
; /* don't close the connection yet */
862 * Get the parameters from the startup packet as C strings. The
863 * packet destination was cleared first so a short packet has zeros
864 * silently added and a long packet is silently truncated.
867 StrNCpy(port
->database
, si
->database
, sizeof(port
->database
) - 1);
868 StrNCpy(port
->user
, si
->user
, sizeof(port
->user
) - 1);
869 StrNCpy(port
->options
, si
->options
, sizeof(port
->options
) - 1);
870 StrNCpy(port
->tty
, si
->tty
, sizeof(port
->tty
) - 1);
872 /* The database defaults to the user name. */
874 if (port
->database
[0] == '\0')
875 StrNCpy(port
->database
, si
->user
, sizeof(port
->database
) - 1);
877 /* Check a user name was given. */
879 if (port
->user
[0] == '\0')
881 PacketSendError(&port
->pktInfo
,
882 "No Postgres username specified in startup packet.");
883 return STATUS_OK
; /* don't close the connection yet */
886 /* Start the authentication itself. */
890 return STATUS_OK
; /* don't close the connection yet */
895 * The client has sent a cancel request packet, not a normal
896 * start-a-new-backend packet. Perform the necessary processing.
897 * Note that in any case, we return STATUS_ERROR to close the
898 * connection immediately. Nothing is sent back to the client.
902 processCancelRequest(Port
*port
, PacketLen len
, void *pkt
)
904 CancelRequestPacket
*canc
= (CancelRequestPacket
*) pkt
;
910 backendPID
= (int) ntohl(canc
->backendPID
);
911 cancelAuthCode
= (long) ntohl(canc
->cancelAuthCode
);
913 /* See if we have a matching backend */
915 for (curr
= DLGetHead(BackendList
); curr
; curr
= DLGetSucc(curr
))
917 bp
= (Backend
*) DLE_VAL(curr
);
918 if (bp
->pid
== backendPID
)
920 if (bp
->cancel_key
== cancelAuthCode
)
922 /* Found a match; signal that backend to cancel current op */
924 fprintf(stderr
, "%s: processCancelRequest: sending SIGINT to process %d\n",
926 kill(bp
->pid
, SIGINT
);
930 /* Right PID, wrong key: no way, Jose */
932 fprintf(stderr
, "%s: processCancelRequest: bad key in cancel request for process %d\n",
939 /* No matching backend */
941 fprintf(stderr
, "%s: processCancelRequest: bad PID in cancel request for process %d\n",
942 progname
, backendPID
);
949 * ConnCreate -- create a local connection data structure
952 ConnCreate(int serverFd
)
957 if (!(port
= (Port
*) calloc(1, sizeof(Port
))))
959 fprintf(stderr
, "%s: ConnCreate: malloc failed\n",
964 if (StreamConnection(serverFd
, port
) != STATUS_OK
)
966 StreamClose(port
->sock
);
972 DLAddHead(PortList
, DLNewElem(port
));
973 RandomSalt(port
->salt
);
974 port
->pktInfo
.state
= Idle
;
981 * reset_shared -- reset shared memory and semaphores
984 reset_shared(short port
)
986 ipc_key
= port
* 1000 + shmem_seq
* 100;
987 CreateSharedMemoryAndSemaphores(ipc_key
);
988 ActiveBackends
= FALSE
;
995 * pmdie -- signal handler for cleaning up after a kill signal.
1002 TPRINTF(TRACE_VERBOSE
, "pmdie %d", postgres_signal_arg
);
1005 * Kill self and/or children processes depending on signal number.
1007 switch (postgres_signal_arg
)
1010 /* Send SIGHUP to all children (update options flags) */
1011 SignalChildren(SIGHUP
);
1015 /* Die without killing children */
1018 /* Shutdown all children with SIGTERM */
1019 SignalChildren(SIGTERM
);
1023 /* Shutdown all children with SIGTERM and SIGKILL, then die */
1024 SignalChildren(SIGTERM
);
1025 for (i
= 0; i
< 10; i
++)
1027 if (!DLGetHead(BackendList
))
1031 if (DLGetHead(BackendList
))
1032 SignalChildren(SIGKILL
);
1035 /* Quick die all children with SIGUSR1 and die */
1036 SignalChildren(SIGUSR1
);
1039 /* Send SIGUSR2 to all children (AsyncNotifyHandler) */
1040 SignalChildren(SIGUSR2
);
1045 /* exit postmaster */
1050 * Reaper -- signal handler to cleanup after a backend (child) dies.
1055 /* GH: replace waitpid for !HAVE_WAITPID. Does this work ? */
1057 int status
; /* backend exit status */
1060 union wait statusp
; /* backend exit status */
1063 int pid
; /* process id of dead backend */
1066 fprintf(stderr
, "%s: reaping dead processes...\n",
1069 while ((pid
= waitpid(-1, &status
, WNOHANG
)) > 0)
1071 CleanupProc(pid
, status
);
1072 pqsignal(SIGCHLD
, reaper
);
1075 while ((pid
= wait3(&statusp
, WNOHANG
, NULL
)) > 0)
1077 CleanupProc(pid
, statusp
.w_status
);
1078 pqsignal(SIGCHLD
, reaper
);
1084 * CleanupProc -- cleanup after terminated backend.
1086 * Remove all local state associated with backend.
1088 * Dillon's note: should log child's exit status in the system log.
1091 CleanupProc(int pid
,
1092 int exitstatus
) /* child's exit status. */
1101 fprintf(stderr
, "%s: CleanupProc: pid %d exited with status %d\n",
1102 progname
, pid
, exitstatus
);
1106 * If a backend dies in an ugly way (i.e. exit status not 0) then we
1107 * must signal all other backends to quickdie. If exit status is zero
1108 * we assume everything is hunky dory and simply remove the backend
1109 * from the active backend list.
1113 curr
= DLGetHead(BackendList
);
1116 bp
= (Backend
*) DLE_VAL(curr
);
1124 curr
= DLGetSucc(curr
);
1132 curr
= DLGetHead(BackendList
);
1135 bp
= (Backend
*) DLE_VAL(curr
);
1137 /* -----------------
1138 * SIGUSR1 is the special signal that says exit
1139 * without proc_exit and let the user know what's going on.
1140 * ProcSemaphoreKill() cleans up the backends semaphore. If
1141 * SendStop is set (-s on command line), then we send a SIGSTOP so
1142 * that we can core dumps from all backends by hand.
1145 sig
= (SendStop
) ? SIGSTOP
: SIGUSR1
;
1149 fprintf(stderr
, "%s: CleanupProc: sending %s to process %d\n",
1152 ? "SIGUSR1" : "SIGSTOP",
1156 ProcRemove(bp
->pid
);
1158 prev
= DLGetPred(curr
);
1163 { /* removed head */
1164 curr
= DLGetHead(BackendList
);
1167 curr
= DLGetSucc(prev
);
1171 * Nothing up my sleeve here, ActiveBackends means that since the last
1172 * time we recreated shared memory and sems another frontend has
1173 * requested and received a connection and I have forked off another
1174 * backend. This prevents me from reinitializing shared stuff more
1175 * than once for the set of backends that caused the failure and were
1178 if (ActiveBackends
== TRUE
&& Reinit
)
1181 fprintf(stderr
, "%s: CleanupProc: reinitializing shared memory and semaphores\n",
1184 reset_shared(PostPortName
);
1189 * Send a signal to all chidren processes.
1192 SignalChildren(int signal
)
1197 int mypid
= getpid();
1199 curr
= DLGetHead(BackendList
);
1202 next
= DLGetSucc(curr
);
1203 bp
= (Backend
*) DLE_VAL(curr
);
1205 if (bp
->pid
!= mypid
)
1207 TPRINTF(TRACE_VERBOSE
,
1208 "SignalChildren: sending signal %d to process %d",
1210 kill(bp
->pid
, signal
);
1218 * BackendStartup -- start backend process
1220 * returns: STATUS_ERROR if the fork/exec failed, STATUS_OK
1225 BackendStartup(Port
*port
)
1227 Backend
*bn
; /* for backend cleanup */
1232 #define NR_ENVIRONMENT_VBL 6
1236 #define NR_ENVIRONMENT_VBL 5
1239 static char envEntry
[NR_ENVIRONMENT_VBL
][2 * ARGV_SIZE
];
1241 for (i
= 0; i
< NR_ENVIRONMENT_VBL
; ++i
)
1242 MemSet(envEntry
[i
], 0, 2 * ARGV_SIZE
);
1245 * Set up the necessary environment variables for the backend This
1246 * should really be some sort of message....
1248 sprintf(envEntry
[0], "POSTPORT=%d", PostPortName
);
1249 putenv(envEntry
[0]);
1250 sprintf(envEntry
[1], "POSTID=%d", NextBackendId
);
1251 putenv(envEntry
[1]);
1252 sprintf(envEntry
[2], "PG_USER=%s", port
->user
);
1253 putenv(envEntry
[2]);
1254 if (!getenv("PGDATA"))
1256 sprintf(envEntry
[3], "PGDATA=%s", DataDir
);
1257 putenv(envEntry
[3]);
1259 sprintf(envEntry
[4], "IPC_KEY=%d", ipc_key
);
1260 putenv(envEntry
[4]);
1263 GetCharSetByHost(ChTable
, port
->raddr
.in
.sin_addr
.s_addr
, DataDir
);
1264 if (*ChTable
!= '\0')
1266 sprintf(envEntry
[5], "PG_RECODETABLE=%s", ChTable
);
1267 putenv(envEntry
[5]);
1272 * Compute the cancel key that will be assigned to this backend. The
1273 * backend will have its own copy in the forked-off process' value of
1274 * MyCancelKey, so that it can transmit the key to the frontend.
1276 MyCancelKey
= PostmasterRandom();
1281 extern char **environ
;
1283 fprintf(stderr
, "%s: BackendStartup: environ dump:\n",
1285 fprintf(stderr
, "-----------------------------------------\n");
1286 for (p
= environ
; *p
; ++p
)
1287 fprintf(stderr
, "\t%s\n", *p
);
1288 fprintf(stderr
, "-----------------------------------------\n");
1292 * Flush stdio channels just before fork, to avoid double-output problems.
1293 * Ideally we'd use fflush(NULL) here, but there are still a few non-ANSI
1294 * stdio libraries out there (like SunOS 4.1.x) that coredump if we do.
1295 * Presently stdout and stderr are the only stdio output channels used
1296 * by the postmaster, so fflush'ing them should be sufficient.
1301 if ((pid
= fork()) == 0)
1303 if (DoBackend(port
))
1305 fprintf(stderr
, "%s child[%d]: BackendStartup: backend startup failed\n",
1306 progname
, (int) getpid());
1316 fprintf(stderr
, "%s: BackendStartup: fork failed\n",
1318 return STATUS_ERROR
;
1322 fprintf(stderr
, "%s: BackendStartup: pid %d user %s db %s socket %d\n",
1323 progname
, pid
, port
->user
, port
->database
,
1326 /* adjust backend counter */
1327 /* XXX Don't know why this is done, but for now backend needs it */
1331 * Everything's been successful, it's safe to add this backend to our
1334 if (!(bn
= (Backend
*) calloc(1, sizeof(Backend
))))
1336 fprintf(stderr
, "%s: BackendStartup: malloc failed\n",
1342 bn
->cancel_key
= MyCancelKey
;
1343 DLAddHead(BackendList
, DLNewElem(bn
));
1345 ActiveBackends
= TRUE
;
1351 * split_opts -- destructively load a string into an argv array
1353 * Since no current POSTGRES arguments require any quoting characters,
1354 * we can use the simple-minded tactic of assuming each set of space-
1355 * delimited characters is a separate argv element.
1357 * If you don't like that, well, we *used* to pass the whole option string
1358 * as ONE argument to execl(), which was even less intelligent...
1361 split_opts(char **argv
, int *argcp
, char *s
)
1371 while (*s
&& !isspace(*s
))
1380 * DoBackend -- set up the argument list and perform an execv system call
1383 * Shouldn't return at all.
1384 * If execv() fails, return status.
1387 DoBackend(Port
*port
)
1389 char execbuf
[MAXPATHLEN
];
1390 char portbuf
[ARGV_SIZE
];
1391 char debugbuf
[ARGV_SIZE
];
1392 char ttybuf
[ARGV_SIZE
+ 1];
1393 char protobuf
[ARGV_SIZE
+ 1];
1394 char argbuf
[(2 * ARGV_SIZE
) + 1];
1397 * each argument takes at least three chars, so we can't have more
1398 * than ARGV_SIZE arguments in (2 * ARGV_SIZE) chars (i.e.,
1399 * port->options plus ExtraOptions)...
1401 char *av
[ARGV_SIZE
];
1402 char dbbuf
[ARGV_SIZE
+ 1];
1409 * Let's clean up ourselves as the postmaster child
1412 on_exit_reset(); /* we don't want the postmaster's
1413 * proc_exit() handlers */
1416 * register signal handlers.
1417 * Thanks to the postmaster, these are currently blocked.
1420 pqsignal(SIGINT
, die
);
1422 pqsignal(SIGHUP
, die
);
1423 pqsignal(SIGTERM
, die
);
1424 pqsignal(SIGPIPE
, die
);
1425 pqsignal(SIGUSR1
, quickdie
);
1426 pqsignal(SIGUSR2
, Async_NotifyHandler
);
1427 pqsignal(SIGFPE
, FloatExceptionHandler
);
1429 pqsignal(SIGCHLD
, SIG_DFL
);
1430 pqsignal(SIGTTIN
, SIG_DFL
);
1431 pqsignal(SIGTTOU
, SIG_DFL
);
1432 pqsignal(SIGCONT
, SIG_DFL
);
1434 /* OK, let's unblock our signals, all together now... */
1435 sigprocmask(SIG_SETMASK
, &oldsigmask
, 0);
1437 /* Close the postmater sockets */
1439 StreamClose(ServerSock_INET
);
1440 StreamClose(ServerSock_UNIX
);
1442 /* Save port for ps status */
1446 * Don't want backend to be able to see the postmaster random number
1447 * generator state. We have to clobber the static random_seed *and*
1448 * start a new random sequence in the random() library function.
1451 gettimeofday(&now
, &tz
);
1452 srandom(now
.tv_usec
);
1454 /* Now, on to standard postgres stuff */
1456 MyProcPid
= getpid();
1458 strncpy(execbuf
, Execfile
, MAXPATHLEN
- 1);
1462 * We need to set our argv[0] to an absolute path name because some
1463 * OS's use this for dynamic loading, like BSDI. Without it, when we
1464 * change directories to the database dir, the dynamic loader can't
1465 * find the base executable and fails. Another advantage is that this
1466 * changes the 'ps' displayed process name on some platforms. It does
1467 * on BSDI. That's a big win.
1473 * This doesn't work on linux and overwrites the only valid pointer to
1474 * the argv buffer. See PS_INIT_STATUS macro.
1476 real_argv
[0] = Execfile
;
1479 /* Tell the backend it is being called from the postmaster */
1483 * Pass the requested debugging level along to the backend. We
1484 * decrement by one; level one debugging in the postmaster traces
1485 * postmaster connection activity, and levels two and higher are
1486 * passed along to the backend. This allows us to watch only the
1487 * postmaster or the postmaster and the backend.
1492 sprintf(debugbuf
, "-d%d", DebugLvl
);
1493 av
[ac
++] = debugbuf
;
1496 /* Pass the requested debugging output file */
1499 strncpy(ttybuf
, port
->tty
, ARGV_SIZE
);
1504 /* Tell the backend the descriptor of the fe/be socket */
1505 sprintf(portbuf
, "-P%d", port
->sock
);
1508 StrNCpy(argbuf
, port
->options
, ARGV_SIZE
);
1509 strncat(argbuf
, ExtraOptions
, ARGV_SIZE
);
1510 argbuf
[(2 * ARGV_SIZE
)] = '\0';
1511 split_opts(av
, &ac
, argbuf
);
1513 /* Tell the backend what protocol the frontend is using. */
1515 sprintf(protobuf
, "-v%u", port
->proto
);
1516 av
[ac
++] = protobuf
;
1518 StrNCpy(dbbuf
, port
->database
, ARGV_SIZE
);
1521 av
[ac
] = (char *) NULL
;
1525 fprintf(stderr
, "%s child[%d]: starting with (",
1526 progname
, MyProcPid
);
1527 for (i
= 0; i
< ac
; ++i
)
1528 fprintf(stderr
, "%s, ", av
[i
]);
1529 fprintf(stderr
, ")\n");
1532 return (PostgresMain(ac
, av
, real_argc
, real_argv
));
1536 * ExitPostmaster -- cleanup
1539 ExitPostmaster(int status
)
1541 /* should cleanup shared memory and kill all backends */
1544 * Not sure of the semantics here. When the Postmaster dies, should
1545 * the backends all be killed? probably not.
1547 if (ServerSock_INET
!= INVALID_SOCK
)
1548 StreamClose(ServerSock_INET
);
1549 if (ServerSock_UNIX
!= INVALID_SOCK
)
1550 StreamClose(ServerSock_UNIX
);
1555 dumpstatus(SIGNAL_ARGS
)
1557 Dlelem
*curr
= DLGetHead(PortList
);
1561 Port
*port
= DLE_VAL(curr
);
1563 fprintf(stderr
, "%s: dumpstatus:\n", progname
);
1564 fprintf(stderr
, "\tsock %d\n", port
->sock
);
1565 curr
= DLGetSucc(curr
);
1573 CharRemap(long int ch
)
1595 RandomSalt(char *salt
)
1597 long rand
= PostmasterRandom();
1599 *salt
= CharRemap(rand
% 62);
1600 *(salt
+ 1) = CharRemap(rand
/ 62);
1607 PostmasterRandom(void)
1610 static bool initialized
= false;
1614 Assert(random_seed
!= 0 && !IsUnderPostmaster
);
1615 srandom(random_seed
);
1619 return random() ^ random_seed
;