Portability fix for old SunOS releases: fflush(NULL)
[pgsql.git] / src / backend / postmaster / postmaster.c
blob8c35f6eeb6c5a45a6d0be5f0d5c9cc66a0a8f41e
1 /*-------------------------------------------------------------------------
3 * postmaster.c--
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
12 * IDENTIFICATION
13 * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.98 1998/11/29 01:51:56 tgl Exp $
15 * NOTES
17 * Initialization:
18 * The Postmaster sets up a few shared memory data structures
19 * for the backends. It should at the very least initialize the
20 * lock manager.
22 * Synchronization:
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.
27 * Garbage Collection:
28 * The Postmaster cleans up after backends if they have an emergency
29 * exit and/or core dump.
31 * Communication:
33 *-------------------------------------------------------------------------
35 /* moved here to prevent double define */
36 #include <sys/param.h> /* for MAXHOSTNAMELEN on most */
37 #ifdef HAVE_NETDB_H
38 #include <netdb.h> /* for MAXHOSTNAMELEN on some */
39 #endif
41 #ifndef MAXHOSTNAMELEN
42 #define MAXHOSTNAMELEN 256
43 #endif
45 #include "postgres.h"
47 #include <signal.h>
48 #include <string.h>
49 #include <stdlib.h>
50 #include <time.h>
52 #if !defined(NO_UNISTD_H)
53 #include <unistd.h>
54 #endif /* !NO_UNISTD_H */
56 #include <ctype.h>
57 #include <sys/types.h> /* for fd_set stuff */
58 #include <sys/stat.h> /* for umask */
59 #include <sys/time.h>
60 #include <sys/socket.h>
61 #ifdef HAVE_LIMITS_H
62 #include <limits.h>
63 #else
64 #include <values.h>
65 #endif
66 #include <sys/wait.h>
68 #include <errno.h>
69 #include <fcntl.h>
70 #include <stdio.h>
72 #ifdef HAVE_SYS_SELECT_H
73 #include <sys/select.h>
74 #endif
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"
83 #include "version.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() */
93 #endif
94 #include "storage/fd.h"
95 #include "utils/trace.h"
97 #if !defined(MAXINT)
98 #define MAXINT INT_MAX
99 #endif
101 #define INVALID_SOCK (-1)
102 #define ARGV_SIZE 64
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.
114 typedef struct bkend
116 int pid; /* process id of backend */
117 long cancel_key; /* cancel key for cancels for this backend */
118 } 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
147 * entirely gone yet.
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
158 * adding to this.
162 static int NextBackendId = MAXINT; /* XXX why? */
163 static char *progname = (char *) NULL;
164 static char **real_argv;
165 static int real_argc;
168 * Default Values
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,
200 newsigmask;
202 #else
203 static int orgsigmask = sigblock(0);
205 #endif
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;
215 extern char *optarg;
216 extern int optind,
217 opterr;
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);
242 #ifdef CYR_RECODE
243 void GetCharSetByHost(char *, int, char *);
245 #endif
247 #ifdef USE_ASSERT_CHECKING
248 int assert_enabled = 1;
250 #endif
252 static void
253 checkDataDir(const char *DataDir, bool *DataDirOK)
255 if (DataDir == NULL)
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",
261 progname);
262 *DataDirOK = false;
264 else
266 char path[MAXPATHLEN];
267 FILE *fp;
269 sprintf(path, "%s%cbase%ctemplate1%cpg_class",
270 DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR);
271 fp = AllocateFile(path, "r");
272 if (fp == NULL)
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);
279 *DataDirOK = false;
281 else
283 char *reason;
285 /* reason ValidatePgVersion failed. NULL if didn't */
287 FreeFile(fp);
289 ValidatePgVersion(DataDir, &reason);
290 if (reason)
292 fprintf(stderr,
293 "Database system in directory %s "
294 "is not compatible with this version of "
295 "Postgres, or we are unable to read the "
296 "PG_VERSION file. "
297 "Explanation from ValidatePgVersion: %s\n\n",
298 DataDir, reason);
299 free(reason);
300 *DataDirOK = false;
302 else
303 *DataDirOK = true;
309 PostmasterMain(int argc, char *argv[])
311 extern int NBuffers; /* from buffer/bufmgr.c */
312 int opt;
313 char *hostName;
314 int status;
315 int silentflag = 0;
316 bool DataDirOK; /* We have a usable PGDATA value */
317 char hostbuf[MAXHOSTNAMELEN];
318 int nonblank_argc;
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.
324 if (argc < 5)
326 int i;
327 char *new_argv[6];
329 for (i = 0; i < argc; i++)
330 new_argv[i] = argv[i];
331 for (; i < 5; i++)
332 new_argv[i] = "";
333 new_argv[5] = NULL;
335 if (!Execfile[0] && FindExec(Execfile, argv[0], "postmaster") < 0)
337 fprintf(stderr, "%s: could not find postmaster to execute...\n",
338 argv[0]);
339 exit(1);
341 new_argv[0] = Execfile;
343 execv(new_argv[0], new_argv);
345 /* How did we get here, error! */
346 perror(new_argv[0]);
347 fprintf(stderr, "PostmasterMain execv failed on %s\n", argv[0]);
348 exit(1);
351 progname = argv[0];
352 real_argv = argv;
353 real_argc = argc;
356 * don't process any dummy args we placed at the end for status
357 * display
359 for (nonblank_argc = argc; nonblank_argc > 0; nonblank_argc--)
360 if (argv[nonblank_argc - 1] != NULL && argv[nonblank_argc - 1][0] != '\0')
361 break;
364 * for security, no dir or file created can be group or other
365 * accessible
367 umask((mode_t) 0077);
369 if (!(hostName = getenv("PGHOST")))
371 if (gethostname(hostbuf, MAXHOSTNAMELEN) < 0)
372 strcpy(hostbuf, "localhost");
373 hostName = hostbuf;
376 MyProcPid = getpid();
377 DataDir = getenv("PGDATA"); /* default value */
379 opterr = 0;
380 while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:dim:Mno:p:Ss")) != EOF)
382 switch (opt)
384 case 'A':
385 #ifndef USE_ASSERT_CHECKING
386 fprintf(stderr, "Assert checking is not enabled\n");
387 #else
390 * Pass this option also to each backend.
392 assert_enabled = atoi(optarg);
393 strcat(ExtraOptions, " -A ");
394 strcat(ExtraOptions, optarg);
395 #endif
396 break;
397 case 'a':
398 /* Can no longer set authentication method. */
399 break;
400 case 'B':
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);
410 break;
411 case 'b':
412 /* Set the backend executable file to use. */
413 if (!ValidateBinary(optarg))
414 strcpy(Execfile, optarg);
415 else
417 fprintf(stderr, "%s: invalid backend \"%s\"\n",
418 progname, optarg);
419 exit(2);
421 break;
422 case 'D':
423 /* Set PGDATA from the command line. */
424 DataDir = optarg;
425 break;
426 case 'd':
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]);
435 optind++;
437 else
438 DebugLvl = 1;
439 pg_options[TRACE_VERBOSE] = DebugLvl;
440 break;
441 case 'i':
442 NetServer = true;
443 break;
444 case 'm':
445 /* Multiplexed backends no longer supported. */
446 break;
447 case 'M':
450 * ignore this flag. This may be passed in because the
451 * program was run as 'postgres -M' instead of
452 * 'postmaster'
454 break;
455 case 'n':
456 /* Don't reinit shared mem after abnormal exit */
457 Reinit = false;
458 break;
459 case 'o':
462 * Other options to pass to the backend on the command
463 * line -- useful only for debugging.
465 strcat(ExtraOptions, " ");
466 strcat(ExtraOptions, optarg);
467 break;
468 case 'p':
469 /* Set PGPORT by hand. */
470 PostPortName = (short) atoi(optarg);
471 break;
472 case 'S':
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
478 * SVR4 and HP-UX.
480 silentflag = 1;
481 break;
482 case 's':
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
488 * everyone.
490 SendStop = true;
491 break;
492 default:
493 /* usage() never returns */
494 usage(progname);
495 break;
498 if (PostPortName == -1)
499 PostPortName = pq_getport();
501 checkDataDir(DataDir, &DataDirOK); /* issues error messages */
502 if (!DataDirOK)
504 fprintf(stderr, "No data directory -- can't proceed.\n");
505 exit(2);
508 if (!Execfile[0] && FindExec(Execfile, argv[0], "postgres") < 0)
510 fprintf(stderr, "%s: could not find backend to execute...\n",
511 argv[0]);
512 exit(1);
515 if (NetServer)
517 status = StreamServerPort(hostName, PostPortName, &ServerSock_INET);
518 if (status != STATUS_OK)
520 fprintf(stderr, "%s: cannot create INET stream port\n",
521 progname);
522 exit(1);
525 status = StreamServerPort(NULL, PostPortName, &ServerSock_UNIX);
526 if (status != STATUS_OK)
528 fprintf(stderr, "%s: cannot create UNIX stream port\n",
529 progname);
530 exit(1);
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();
544 if (silentflag)
545 pmdaemonize();
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 */
569 static void
570 pmdaemonize(void)
572 int i;
574 if (fork())
575 _exit(0);
576 /* GH: If there's no setsid(), we hopefully don't need silent mode.
577 * Until there's a better solution.
579 #ifdef HAVE_SETSID
580 if (setsid() < 0)
582 fprintf(stderr, "%s: ", progname);
583 perror("cannot disassociate from controlling TTY");
584 exit(1);
586 #endif
587 i = open(NULL_DEV, O_RDWR);
588 dup2(i, 0);
589 dup2(i, 1);
590 dup2(i, 2);
591 close(i);
594 static void
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");
600 #endif
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");
612 exit(1);
615 static int
616 ServerLoop(void)
618 fd_set readmask,
619 writemask;
620 int nSockets;
621 Dlelem *curr;
622 struct timeval now,
623 later;
624 struct timezone tz;
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);
634 #endif
636 for (;;)
638 Port *port;
639 fd_set rmask,
640 wmask;
642 #ifdef HAVE_SIGPROCMASK
643 sigprocmask(SIG_SETMASK, &oldsigmask, 0);
644 #else
645 sigsetmask(orgsigmask);
646 #endif
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)
653 if (errno == EINTR)
654 continue;
655 fprintf(stderr, "%s: ServerLoop: select failed\n",
656 progname);
657 return STATUS_ERROR;
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);
685 #else
686 sigblock(sigmask(SIGCHLD)); /* XXX[TRH] portability */
687 #endif
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,
695 readStartupPacket,
696 (void *) port);
698 if (ServerSock_INET != INVALID_SOCK &&
699 FD_ISSET(ServerSock_INET, &rmask) &&
700 (port = ConnCreate(ServerSock_INET)) != NULL)
701 PacketReceiveSetup(&port->pktInfo,
702 readStartupPacket,
703 (void *) port);
705 /* Build up new masks for select(). */
707 nSockets = initMasks(&readmask, &writemask);
709 curr = DLGetHead(PortList);
711 while (curr)
713 Port *port = (Port *) DLE_VAL(curr);
714 int status = STATUS_OK;
715 Dlelem *next;
717 if (FD_ISSET(port->sock, &rmask))
719 if (DebugLvl > 1)
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))
729 if (DebugLvl > 1)
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
754 * by the backend.
757 if (BackendStartup(port) != STATUS_OK)
758 PacketSendError(&port->pktInfo,
759 "Backend startup failed");
760 else
761 status = STATUS_ERROR;
764 /* Close the connection if required. */
766 if (status != STATUS_OK)
768 StreamClose(port->sock);
769 DLRemove(curr);
770 free(port);
771 DLFreeElem(curr);
773 else
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);
782 else
783 FD_SET(port->sock, &readmask);
786 curr = next;
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.
797 static int
798 initMasks(fd_set *rmask, fd_set *wmask)
800 int nsocks = -1;
802 FD_ZERO(rmask);
803 FD_ZERO(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;
821 return nsocks + 1;
826 * Called when the startup packet has been read.
829 static int
830 readStartupPacket(void *arg, PacketLen len, void *pkt)
832 Port *port;
833 StartupPacket *si;
835 port = (Port *) arg;
836 si = (StartupPacket *) pkt;
839 * The first field is either a protocol version number or a special
840 * request code.
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. */
888 be_recvauth(port);
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.
901 static int
902 processCancelRequest(Port *port, PacketLen len, void *pkt)
904 CancelRequestPacket *canc = (CancelRequestPacket *) pkt;
905 int backendPID;
906 long cancelAuthCode;
907 Dlelem *curr;
908 Backend *bp;
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 */
923 if (DebugLvl)
924 fprintf(stderr, "%s: processCancelRequest: sending SIGINT to process %d\n",
925 progname, bp->pid);
926 kill(bp->pid, SIGINT);
928 else
930 /* Right PID, wrong key: no way, Jose */
931 if (DebugLvl)
932 fprintf(stderr, "%s: processCancelRequest: bad key in cancel request for process %d\n",
933 progname, bp->pid);
935 return STATUS_ERROR;
939 /* No matching backend */
940 if (DebugLvl)
941 fprintf(stderr, "%s: processCancelRequest: bad PID in cancel request for process %d\n",
942 progname, backendPID);
944 return STATUS_ERROR;
949 * ConnCreate -- create a local connection data structure
951 static Port *
952 ConnCreate(int serverFd)
954 Port *port;
957 if (!(port = (Port *) calloc(1, sizeof(Port))))
959 fprintf(stderr, "%s: ConnCreate: malloc failed\n",
960 progname);
961 ExitPostmaster(1);
964 if (StreamConnection(serverFd, port) != STATUS_OK)
966 StreamClose(port->sock);
967 free(port);
968 port = NULL;
970 else
972 DLAddHead(PortList, DLNewElem(port));
973 RandomSalt(port->salt);
974 port->pktInfo.state = Idle;
977 return port;
981 * reset_shared -- reset shared memory and semaphores
983 static void
984 reset_shared(short port)
986 ipc_key = port * 1000 + shmem_seq * 100;
987 CreateSharedMemoryAndSemaphores(ipc_key);
988 ActiveBackends = FALSE;
989 shmem_seq += 1;
990 if (shmem_seq >= 10)
991 shmem_seq -= 10;
995 * pmdie -- signal handler for cleaning up after a kill signal.
997 static void
998 pmdie(SIGNAL_ARGS)
1000 int i;
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)
1009 case SIGHUP:
1010 /* Send SIGHUP to all children (update options flags) */
1011 SignalChildren(SIGHUP);
1012 /* Don't die */
1013 return;
1014 case SIGINT:
1015 /* Die without killing children */
1016 break;
1017 case SIGQUIT:
1018 /* Shutdown all children with SIGTERM */
1019 SignalChildren(SIGTERM);
1020 /* Don't die */
1021 return;
1022 case 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))
1028 break;
1029 sleep(1);
1031 if (DLGetHead(BackendList))
1032 SignalChildren(SIGKILL);
1033 break;
1034 case SIGUSR1:
1035 /* Quick die all children with SIGUSR1 and die */
1036 SignalChildren(SIGUSR1);
1037 break;
1038 case SIGUSR2:
1039 /* Send SIGUSR2 to all children (AsyncNotifyHandler) */
1040 SignalChildren(SIGUSR2);
1041 /* Don't die */
1042 return;
1045 /* exit postmaster */
1046 proc_exit(0);
1050 * Reaper -- signal handler to cleanup after a backend (child) dies.
1052 static void
1053 reaper(SIGNAL_ARGS)
1055 /* GH: replace waitpid for !HAVE_WAITPID. Does this work ? */
1056 #ifdef HAVE_WAITPID
1057 int status; /* backend exit status */
1059 #else
1060 union wait statusp; /* backend exit status */
1062 #endif
1063 int pid; /* process id of dead backend */
1065 if (DebugLvl)
1066 fprintf(stderr, "%s: reaping dead processes...\n",
1067 progname);
1068 #ifdef HAVE_WAITPID
1069 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
1071 CleanupProc(pid, status);
1072 pqsignal(SIGCHLD, reaper);
1074 #else
1075 while ((pid = wait3(&statusp, WNOHANG, NULL)) > 0)
1077 CleanupProc(pid, statusp.w_status);
1078 pqsignal(SIGCHLD, reaper);
1080 #endif
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.
1090 static void
1091 CleanupProc(int pid,
1092 int exitstatus) /* child's exit status. */
1094 Dlelem *prev,
1095 *curr;
1096 Backend *bp;
1097 int sig;
1099 if (DebugLvl)
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.
1111 if (!exitstatus)
1113 curr = DLGetHead(BackendList);
1114 while (curr)
1116 bp = (Backend *) DLE_VAL(curr);
1117 if (bp->pid == pid)
1119 DLRemove(curr);
1120 free(bp);
1121 DLFreeElem(curr);
1122 break;
1124 curr = DLGetSucc(curr);
1127 ProcRemove(pid);
1129 return;
1132 curr = DLGetHead(BackendList);
1133 while (curr)
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.
1143 * -----------------
1145 sig = (SendStop) ? SIGSTOP : SIGUSR1;
1146 if (bp->pid != pid)
1148 if (DebugLvl)
1149 fprintf(stderr, "%s: CleanupProc: sending %s to process %d\n",
1150 progname,
1151 (sig == SIGUSR1)
1152 ? "SIGUSR1" : "SIGSTOP",
1153 bp->pid);
1154 kill(bp->pid, sig);
1156 ProcRemove(bp->pid);
1158 prev = DLGetPred(curr);
1159 DLRemove(curr);
1160 free(bp);
1161 DLFreeElem(curr);
1162 if (!prev)
1163 { /* removed head */
1164 curr = DLGetHead(BackendList);
1165 continue;
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
1176 * killed off.
1178 if (ActiveBackends == TRUE && Reinit)
1180 if (DebugLvl)
1181 fprintf(stderr, "%s: CleanupProc: reinitializing shared memory and semaphores\n",
1182 progname);
1183 shmem_exit(0);
1184 reset_shared(PostPortName);
1189 * Send a signal to all chidren processes.
1191 static void
1192 SignalChildren(int signal)
1194 Dlelem *curr,
1195 *next;
1196 Backend *bp;
1197 int mypid = getpid();
1199 curr = DLGetHead(BackendList);
1200 while (curr)
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",
1209 signal, bp->pid);
1210 kill(bp->pid, signal);
1213 curr = next;
1218 * BackendStartup -- start backend process
1220 * returns: STATUS_ERROR if the fork/exec failed, STATUS_OK
1221 * otherwise.
1224 static int
1225 BackendStartup(Port *port)
1227 Backend *bn; /* for backend cleanup */
1228 int pid,
1231 #ifdef CYR_RECODE
1232 #define NR_ENVIRONMENT_VBL 6
1233 char ChTable[80];
1235 #else
1236 #define NR_ENVIRONMENT_VBL 5
1237 #endif
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]);
1262 #ifdef CYR_RECODE
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]);
1269 #endif
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();
1278 if (DebugLvl > 2)
1280 char **p;
1281 extern char **environ;
1283 fprintf(stderr, "%s: BackendStartup: environ dump:\n",
1284 progname);
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.
1298 fflush(stdout);
1299 fflush(stderr);
1301 if ((pid = fork()) == 0)
1302 { /* child */
1303 if (DoBackend(port))
1305 fprintf(stderr, "%s child[%d]: BackendStartup: backend startup failed\n",
1306 progname, (int) getpid());
1307 exit(1);
1309 else
1310 exit(0);
1313 /* in parent */
1314 if (pid < 0)
1316 fprintf(stderr, "%s: BackendStartup: fork failed\n",
1317 progname);
1318 return STATUS_ERROR;
1321 if (DebugLvl)
1322 fprintf(stderr, "%s: BackendStartup: pid %d user %s db %s socket %d\n",
1323 progname, pid, port->user, port->database,
1324 port->sock);
1326 /* adjust backend counter */
1327 /* XXX Don't know why this is done, but for now backend needs it */
1328 NextBackendId -= 1;
1331 * Everything's been successful, it's safe to add this backend to our
1332 * list of backends.
1334 if (!(bn = (Backend *) calloc(1, sizeof(Backend))))
1336 fprintf(stderr, "%s: BackendStartup: malloc failed\n",
1337 progname);
1338 ExitPostmaster(1);
1341 bn->pid = pid;
1342 bn->cancel_key = MyCancelKey;
1343 DLAddHead(BackendList, DLNewElem(bn));
1345 ActiveBackends = TRUE;
1347 return STATUS_OK;
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...
1360 static void
1361 split_opts(char **argv, int *argcp, char *s)
1363 int i = *argcp;
1365 while (s && *s)
1367 while (isspace(*s))
1368 ++s;
1369 if (*s)
1370 argv[i++] = s;
1371 while (*s && !isspace(*s))
1372 ++s;
1373 if (isspace(*s))
1374 *s++ = '\0';
1376 *argcp = i;
1380 * DoBackend -- set up the argument list and perform an execv system call
1382 * returns:
1383 * Shouldn't return at all.
1384 * If execv() fails, return status.
1386 static int
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];
1403 int ac = 0;
1404 int i;
1405 struct timeval now;
1406 struct timezone tz;
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 */
1415 /* ----------------
1416 * register signal handlers.
1417 * Thanks to the postmaster, these are currently blocked.
1418 * ----------------
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 */
1438 if (NetServer)
1439 StreamClose(ServerSock_INET);
1440 StreamClose(ServerSock_UNIX);
1442 /* Save port for ps status */
1443 MyProcPort = port;
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.
1450 random_seed = 0;
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);
1459 av[ac++] = execbuf;
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.
1470 #ifndef linux
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;
1477 #endif
1479 /* Tell the backend it is being called from the postmaster */
1480 av[ac++] = "-p";
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.
1490 if (DebugLvl > 1)
1492 sprintf(debugbuf, "-d%d", DebugLvl);
1493 av[ac++] = debugbuf;
1496 /* Pass the requested debugging output file */
1497 if (port->tty[0])
1499 strncpy(ttybuf, port->tty, ARGV_SIZE);
1500 av[ac++] = "-o";
1501 av[ac++] = ttybuf;
1504 /* Tell the backend the descriptor of the fe/be socket */
1505 sprintf(portbuf, "-P%d", port->sock);
1506 av[ac++] = portbuf;
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);
1519 av[ac++] = dbbuf;
1521 av[ac] = (char *) NULL;
1523 if (DebugLvl > 1)
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
1538 static void
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);
1551 proc_exit(status);
1554 static void
1555 dumpstatus(SIGNAL_ARGS)
1557 Dlelem *curr = DLGetHead(PortList);
1559 while (curr)
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);
1570 * CharRemap
1572 static char
1573 CharRemap(long int ch)
1576 if (ch < 0)
1577 ch = -ch;
1579 ch = ch % 62;
1580 if (ch < 26)
1581 return 'A' + ch;
1583 ch -= 26;
1584 if (ch < 26)
1585 return 'a' + ch;
1587 ch -= 26;
1588 return '0' + ch;
1592 * RandomSalt
1594 static void
1595 RandomSalt(char *salt)
1597 long rand = PostmasterRandom();
1599 *salt = CharRemap(rand % 62);
1600 *(salt + 1) = CharRemap(rand / 62);
1604 * PostmasterRandom
1606 static long
1607 PostmasterRandom(void)
1610 static bool initialized = false;
1612 if (!initialized)
1614 Assert(random_seed != 0 && !IsUnderPostmaster);
1615 srandom(random_seed);
1616 initialized = true;
1619 return random() ^ random_seed;