postmaster.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:41k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  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.
  8.  *
  9.  * Copyright (c) 1994, Regents of the University of California
  10.  *
  11.  *
  12.  * IDENTIFICATION
  13.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.108 1999/07/07 17:17:48 momjian Exp $
  14.  *
  15.  * NOTES
  16.  *
  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.
  21.  *
  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.
  26.  *
  27.  * Garbage Collection:
  28.  * The Postmaster cleans up after backends if they have an emergency
  29.  * exit and/or core dump.
  30.  *
  31.  * Communication:
  32.  *
  33.  *-------------------------------------------------------------------------
  34.  */
  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
  40. #ifndef MAXHOSTNAMELEN
  41. #define MAXHOSTNAMELEN 256
  42. #endif
  43. #include "postgres.h"
  44. #include <signal.h>
  45. #include <string.h>
  46. #include <stdlib.h>
  47. #include <time.h>
  48. #if !defined(NO_UNISTD_H)
  49. #include <unistd.h>
  50. #endif  /* !NO_UNISTD_H */
  51. #include <ctype.h>
  52. #include <sys/types.h> /* for fd_set stuff */
  53. #include <sys/stat.h> /* for umask */
  54. #include <sys/time.h>
  55. #include <sys/socket.h>
  56. #ifdef HAVE_LIMITS_H
  57. #include <limits.h>
  58. #else
  59. #include <values.h>
  60. #endif
  61. #include <sys/wait.h>
  62. #include <errno.h>
  63. #include <fcntl.h>
  64. #include <stdio.h>
  65. #ifdef HAVE_SYS_SELECT_H
  66. #include <sys/select.h>
  67. #endif
  68. #ifdef __CYGWIN32__
  69. #include <getopt.h>
  70. #endif
  71. #include "storage/ipc.h"
  72. #include "libpq/libpq.h"
  73. #include "libpq/auth.h"
  74. #include "libpq/pqcomm.h"
  75. #include "libpq/pqsignal.h"
  76. #include "libpq/crypt.h"
  77. #include "miscadmin.h"
  78. #include "version.h"
  79. #include "lib/dllist.h"
  80. #include "tcop/tcopprot.h"
  81. #include "commands/async.h"
  82. #include "nodes/nodes.h"
  83. #include "utils/mcxt.h"
  84. #include "storage/proc.h"
  85. #include "utils/elog.h"
  86. #ifndef HAVE_GETHOSTNAME
  87. #include "port-protos.h" /* For gethostname() */
  88. #endif
  89. #include "storage/fd.h"
  90. #include "utils/trace.h"
  91. #if !defined(MAXINT)
  92. #define MAXINT    INT_MAX
  93. #endif
  94. #define INVALID_SOCK (-1)
  95. #define ARGV_SIZE 64
  96.  /*
  97.   * Max time in seconds for socket to linger (close() to block) waiting
  98.   * for frontend to retrieve its message from us.
  99.   */
  100. /*
  101.  * Info for garbage collection.  Whenever a process dies, the Postmaster
  102.  * cleans up after it. Currently, NO information is required for cleanup,
  103.  * but I left this structure around in case that changed.
  104.  */
  105. typedef struct bkend
  106. {
  107. int pid; /* process id of backend */
  108. long cancel_key; /* cancel key for cancels for this backend */
  109. } Backend;
  110. Port    *MyBackendPort = NULL;
  111. /* list of active backends.  For garbage collection only now. */
  112. static Dllist *BackendList;
  113. /* list of ports associated with still open, but incomplete connections */
  114. static Dllist *PortList;
  115. static unsigned short PostPortName = 0;
  116. static short ActiveBackends = FALSE;
  117.  /*
  118.   * This is a boolean indicating that there is at least one backend that
  119.   * is accessing the current shared memory and semaphores. Between the
  120.   * time that we start up, or throw away shared memory segments and start
  121.   * over, and the time we generate the next backend (because we received a
  122.   * connection request), it is false. Other times, it is true.
  123.   */
  124. static short shmem_seq = 0;
  125.  /*
  126.   * This is a sequence number that indicates how many times we've had to
  127.   * throw away the shared memory and start over because we doubted its
  128.   * integrity. It starts off at zero and is incremented every time we
  129.   * start over.  We use this to ensure that we use a new IPC shared memory
  130.   * key for the new shared memory segment in case the old segment isn't
  131.   * entirely gone yet.
  132.   *
  133.   * The sequence actually cycles back to 0 after 9, so pathologically there
  134.   * could be an IPC failure if 10 sets of backends are all stuck and won't
  135.   * release IPC resources.
  136.   */
  137. static IpcMemoryKey ipc_key;
  138.  /*
  139.   * This is the base IPC shared memory key.  Other keys are generated by
  140.   * adding to this.
  141.   */
  142. static int MaxBackends = DEF_MAXBACKENDS;
  143.  /*
  144.   * MaxBackends is the actual limit on the number of backends we will
  145.   * start. The default is established by configure, but it can be
  146.   * readjusted from 1..MAXBACKENDS with the postmaster -N switch. Note
  147.   * that a larger MaxBackends value will increase the size of the shared
  148.   * memory area as well as cause the postmaster to grab more kernel
  149.   * semaphores, even if you never actually use that many backends.
  150.   */
  151. static int NextBackendTag = MAXINT; /* XXX why count down not up? */
  152. static char *progname = (char *) NULL;
  153. static char **real_argv;
  154. static int real_argc;
  155. /*
  156.  * Default Values
  157.  */
  158. static char Execfile[MAXPATHLEN] = "";
  159. static int ServerSock_INET = INVALID_SOCK; /* stream socket server */
  160. #ifndef __CYGWIN32__
  161. static int ServerSock_UNIX = INVALID_SOCK; /* stream socket server */
  162. #endif
  163. /*
  164.  * Set by the -o option
  165.  */
  166. static char ExtraOptions[MAXPATHLEN] = "";
  167. /*
  168.  * These globals control the behavior of the postmaster in case some
  169.  * backend dumps core. Normally, it kills all peers of the dead backend
  170.  * and reinitializes shared memory.  By specifying -s or -n, we can have
  171.  * the postmaster stop (rather than kill) peers and not reinitialize
  172.  * shared data structures.
  173.  */
  174. static bool Reinit = true;
  175. static int SendStop = false;
  176. static bool NetServer = false; /* if not zero, postmaster listen for
  177.  * non-local connections */
  178. /*
  179.  * GH: For !HAVE_SIGPROCMASK (NEXTSTEP), TRH implemented an
  180.  * alternative interface.
  181.  */
  182. #ifdef HAVE_SIGPROCMASK
  183. static sigset_t oldsigmask,
  184. newsigmask;
  185. #else
  186. static int orgsigmask = sigblock(0);
  187. #endif
  188. /*
  189.  * State for assigning random salts and cancel keys.
  190.  * Also, the global MyCancelKey passes the cancel key assigned to a given
  191.  * backend from the postmaster to that backend (via fork).
  192.  */
  193. static unsigned int random_seed = 0;
  194. extern char *optarg;
  195. extern int optind,
  196. opterr;
  197. /*
  198.  * postmaster.c - function prototypes
  199.  */
  200. static void pmdaemonize(void);
  201. static Port *ConnCreate(int serverFd);
  202. static void reset_shared(unsigned short port);
  203. static void pmdie(SIGNAL_ARGS);
  204. static void reaper(SIGNAL_ARGS);
  205. static void dumpstatus(SIGNAL_ARGS);
  206. static void CleanupProc(int pid, int exitstatus);
  207. static int DoBackend(Port *port);
  208. static void ExitPostmaster(int status);
  209. static void usage(const char *);
  210. static int ServerLoop(void);
  211. static int BackendStartup(Port *port);
  212. static int readStartupPacket(void *arg, PacketLen len, void *pkt);
  213. static int processCancelRequest(Port *port, PacketLen len, void *pkt);
  214. static int initMasks(fd_set *rmask, fd_set *wmask);
  215. static long PostmasterRandom(void);
  216. static void RandomSalt(char *salt);
  217. static void SignalChildren(SIGNAL_ARGS);
  218. static int CountChildren(void);
  219. #ifdef CYR_RECODE
  220. void GetCharSetByHost(char *, int, char *);
  221. #endif
  222. #ifdef USE_ASSERT_CHECKING
  223. int assert_enabled = 1;
  224. #endif
  225. static void
  226. checkDataDir(const char *DataDir, bool *DataDirOK)
  227. {
  228. if (DataDir == NULL)
  229. {
  230. fprintf(stderr, "%s does not know where to find the database system "
  231. "data.  You must specify the directory that contains the "
  232. "database system either by specifying the -D invocation "
  233.  "option or by setting the PGDATA environment variable.nn",
  234. progname);
  235. *DataDirOK = false;
  236. }
  237. else
  238. {
  239. char path[MAXPATHLEN];
  240. FILE    *fp;
  241. sprintf(path, "%s%cbase%ctemplate1%cpg_class",
  242. DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR);
  243. #ifndef __CYGWIN32__
  244. fp = AllocateFile(path, "r");
  245. #else
  246. fp = AllocateFile(path, "rb");
  247. #endif
  248. if (fp == NULL)
  249. {
  250. fprintf(stderr, "%s does not find the database system.  "
  251. "Expected to find it "
  252.    "in the PGDATA directory "%s", but unable to open file "
  253. "with pathname "%s".nn",
  254. progname, DataDir, path);
  255. *DataDirOK = false;
  256. }
  257. else
  258. {
  259. char    *reason;
  260. /* reason ValidatePgVersion failed.  NULL if didn't */
  261. FreeFile(fp);
  262. ValidatePgVersion(DataDir, &reason);
  263. if (reason)
  264. {
  265. fprintf(stderr,
  266. "Database system in directory %s "
  267. "is not compatible with this version of "
  268. "Postgres, or we are unable to read the "
  269. "PG_VERSION file.  "
  270. "Explanation from ValidatePgVersion: %snn",
  271. DataDir, reason);
  272. free(reason);
  273. *DataDirOK = false;
  274. }
  275. else
  276. *DataDirOK = true;
  277. }
  278. }
  279. }
  280. int
  281. PostmasterMain(int argc, char *argv[])
  282. {
  283. extern int NBuffers; /* from buffer/bufmgr.c */
  284. int opt;
  285. char    *hostName;
  286. int status;
  287. int silentflag = 0;
  288. bool DataDirOK; /* We have a usable PGDATA value */
  289. char hostbuf[MAXHOSTNAMELEN];
  290. int nonblank_argc;
  291. /*
  292.  * We need three params so we can display status.  If we don't get
  293.  * them from the user, let's make them ourselves.
  294.  */
  295. if (argc < 5)
  296. {
  297. int i;
  298. char    *new_argv[6];
  299. for (i = 0; i < argc; i++)
  300. new_argv[i] = argv[i];
  301. for (; i < 5; i++)
  302. new_argv[i] = "";
  303. new_argv[5] = NULL;
  304. if (!Execfile[0] && FindExec(Execfile, argv[0], "postmaster") < 0)
  305. {
  306. fprintf(stderr, "%s: could not find postmaster to execute...n",
  307. argv[0]);
  308. exit(1);
  309. }
  310. new_argv[0] = Execfile;
  311. execv(new_argv[0], new_argv);
  312. /* How did we get here, error! */
  313. perror(new_argv[0]);
  314. fprintf(stderr, "PostmasterMain execv failed on %sn", argv[0]);
  315. exit(1);
  316. }
  317. progname = argv[0];
  318. real_argv = argv;
  319. real_argc = argc;
  320. /*
  321.  * don't process any dummy args we placed at the end for status
  322.  * display
  323.  */
  324. for (nonblank_argc = argc; nonblank_argc > 0; nonblank_argc--)
  325. if (argv[nonblank_argc - 1] != NULL && argv[nonblank_argc - 1][0] != '')
  326. break;
  327. /*
  328.  * for security, no dir or file created can be group or other
  329.  * accessible
  330.  */
  331. umask((mode_t) 0077);
  332. if (!(hostName = getenv("PGHOST")))
  333. {
  334. if (gethostname(hostbuf, MAXHOSTNAMELEN) < 0)
  335. strcpy(hostbuf, "localhost");
  336. hostName = hostbuf;
  337. }
  338. MyProcPid = getpid();
  339. DataDir = getenv("PGDATA"); /* default value */
  340. opterr = 0;
  341. while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:dim:MN:no:p:Ss")) != EOF)
  342. {
  343. switch (opt)
  344. {
  345. case 'A':
  346. #ifndef USE_ASSERT_CHECKING
  347. fprintf(stderr, "Assert checking is not enabledn");
  348. #else
  349. /*
  350.  * Pass this option also to each backend.
  351.  */
  352. assert_enabled = atoi(optarg);
  353. strcat(ExtraOptions, " -A ");
  354. strcat(ExtraOptions, optarg);
  355. #endif
  356. break;
  357. case 'a':
  358. /* Can no longer set authentication method. */
  359. break;
  360. case 'B':
  361. /*
  362.  * The number of buffers to create.  Setting this option
  363.  * means we have to start each backend with a -B # to make
  364.  * sure they know how many buffers were allocated.
  365.  */
  366. NBuffers = atoi(optarg);
  367. strcat(ExtraOptions, " -B ");
  368. strcat(ExtraOptions, optarg);
  369. break;
  370. case 'b':
  371. /* Set the backend executable file to use. */
  372. if (!ValidateBinary(optarg))
  373. strcpy(Execfile, optarg);
  374. else
  375. {
  376. fprintf(stderr, "%s: invalid backend "%s"n",
  377. progname, optarg);
  378. exit(2);
  379. }
  380. break;
  381. case 'D':
  382. /* Set PGDATA from the command line. */
  383. DataDir = optarg;
  384. break;
  385. case 'd':
  386. /*
  387.  * Turn on debugging for the postmaster and the backend
  388.  * servers descended from it.
  389.  */
  390. if ((optind < nonblank_argc) && *argv[optind] != '-')
  391. {
  392. DebugLvl = atoi(argv[optind]);
  393. optind++;
  394. }
  395. else
  396. DebugLvl = 1;
  397. pg_options[TRACE_VERBOSE] = DebugLvl;
  398. break;
  399. case 'i':
  400. NetServer = true;
  401. break;
  402. case 'm':
  403. /* Multiplexed backends no longer supported. */
  404. break;
  405. case 'M':
  406. /*
  407.  * ignore this flag.  This may be passed in because the
  408.  * program was run as 'postgres -M' instead of
  409.  * 'postmaster'
  410.  */
  411. break;
  412. case 'N':
  413. /*
  414.  * The max number of backends to start. Can't set to less
  415.  * than 1 or more than compiled-in limit.
  416.  */
  417. MaxBackends = atoi(optarg);
  418. if (MaxBackends < 1)
  419. MaxBackends = 1;
  420. if (MaxBackends > MAXBACKENDS)
  421. MaxBackends = MAXBACKENDS;
  422. break;
  423. case 'n':
  424. /* Don't reinit shared mem after abnormal exit */
  425. Reinit = false;
  426. break;
  427. case 'o':
  428. /*
  429.  * Other options to pass to the backend on the command
  430.  * line -- useful only for debugging.
  431.  */
  432. strcat(ExtraOptions, " ");
  433. strcat(ExtraOptions, optarg);
  434. break;
  435. case 'p':
  436. /* Set PGPORT by hand. */
  437. PostPortName = (unsigned short) atoi(optarg);
  438. break;
  439. case 'S':
  440. /*
  441.  * Start in 'S'ilent mode (disassociate from controlling
  442.  * tty). You may also think of this as 'S'ysV mode since
  443.  * it's most badly needed on SysV-derived systems like
  444.  * SVR4 and HP-UX.
  445.  */
  446. silentflag = 1;
  447. break;
  448. case 's':
  449. /*
  450.  * In the event that some backend dumps core, send
  451.  * SIGSTOP, rather than SIGUSR1, to all its peers. This
  452.  * lets the wily post_hacker collect core dumps from
  453.  * everyone.
  454.  */
  455. SendStop = true;
  456. break;
  457. default:
  458. /* usage() never returns */
  459. usage(progname);
  460. break;
  461. }
  462. }
  463. /*
  464.  * Select default values for switches where needed
  465.  */
  466. if (PostPortName == 0)
  467. PostPortName = (unsigned short)pq_getport();
  468. /*
  469.  * Check for invalid combinations of switches
  470.  */
  471. if (NBuffers < 2 * MaxBackends || NBuffers < 16)
  472. {
  473. /* Do not accept -B so small that backends are likely to starve for
  474.  * lack of buffers.  The specific choices here are somewhat arbitrary.
  475.  */
  476. fprintf(stderr, "%s: -B must be at least twice -N and at least 16.n",
  477. progname);
  478. exit(1);
  479. }
  480. checkDataDir(DataDir, &DataDirOK); /* issues error messages */
  481. if (!DataDirOK)
  482. {
  483. fprintf(stderr, "No data directory -- can't proceed.n");
  484. exit(2);
  485. }
  486. if (!Execfile[0] && FindExec(Execfile, argv[0], "postgres") < 0)
  487. {
  488. fprintf(stderr, "%s: could not find backend to execute...n",
  489. argv[0]);
  490. exit(1);
  491. }
  492. if (NetServer)
  493. {
  494. status = StreamServerPort(hostName, PostPortName, &ServerSock_INET);
  495. if (status != STATUS_OK)
  496. {
  497. fprintf(stderr, "%s: cannot create INET stream portn",
  498. progname);
  499. exit(1);
  500. }
  501. }
  502. #ifndef __CYGWIN32__
  503. status = StreamServerPort(NULL, PostPortName, &ServerSock_UNIX);
  504. if (status != STATUS_OK)
  505. {
  506. fprintf(stderr, "%s: cannot create UNIX stream portn",
  507. progname);
  508. exit(1);
  509. }
  510. #endif
  511. /* set up shared memory and semaphores */
  512. EnableMemoryContext(TRUE);
  513. reset_shared(PostPortName);
  514. /*
  515.  * Initialize the list of active backends. This list is only used for
  516.  * garbage collecting the backend processes.
  517.  */
  518. BackendList = DLNewList();
  519. PortList = DLNewList();
  520. if (silentflag)
  521. pmdaemonize();
  522. /*
  523.  * Set up signal handlers for the postmaster process.
  524.  */
  525. pqsignal(SIGHUP, pmdie); /* send SIGHUP, don't die */
  526. pqsignal(SIGINT, pmdie); /* die */
  527. pqsignal(SIGQUIT, pmdie); /* send SIGTERM and die */
  528. pqsignal(SIGTERM, pmdie); /* send SIGTERM,SIGKILL and die */
  529. pqsignal(SIGPIPE, SIG_IGN); /* ignored */
  530. pqsignal(SIGUSR1, pmdie); /* send SIGUSR1 and die */
  531. pqsignal(SIGUSR2, pmdie); /* send SIGUSR2, don't die */
  532. pqsignal(SIGCHLD, reaper); /* handle child termination */
  533. pqsignal(SIGTTIN, SIG_IGN); /* ignored */
  534. pqsignal(SIGTTOU, SIG_IGN); /* ignored */
  535. pqsignal(SIGWINCH, dumpstatus); /* dump port status */
  536. status = ServerLoop();
  537. ExitPostmaster(status != STATUS_OK);
  538. return 0; /* not reached */
  539. }
  540. static void
  541. pmdaemonize(void)
  542. {
  543. int i;
  544. if (fork())
  545. _exit(0);
  546. /* GH: If there's no setsid(), we hopefully don't need silent mode.
  547.  * Until there's a better solution.
  548.  */
  549. #ifdef HAVE_SETSID
  550. if (setsid() < 0)
  551. {
  552. fprintf(stderr, "%s: ", progname);
  553. perror("cannot disassociate from controlling TTY");
  554. exit(1);
  555. }
  556. #endif
  557. #ifndef __CYGWIN32__
  558. i = open(NULL_DEV, O_RDWR);
  559. #else
  560. i = open(NULL_DEV, O_RDWR | O_BINARY);
  561. #endif
  562. dup2(i, 0);
  563. dup2(i, 1);
  564. dup2(i, 2);
  565. close(i);
  566. }
  567. static void
  568. usage(const char *progname)
  569. {
  570. fprintf(stderr, "usage: %s [options]n", progname);
  571. #ifdef USE_ASSERT_CHECKING
  572. fprintf(stderr, "t-A [1|0]tenable/disable runtime assert checkingn");
  573. #endif
  574. fprintf(stderr, "t-B nbufstset number of shared buffersn");
  575. fprintf(stderr, "t-D datadirtset data directoryn");
  576. fprintf(stderr, "t-S ttsilent mode (disassociate from tty)n");
  577. fprintf(stderr, "t-a systemtuse this authentication systemn");
  578. fprintf(stderr, "t-b backendtuse a specific backend server executablen");
  579. fprintf(stderr, "t-d [1|2|3]tset debugging leveln");
  580. fprintf(stderr, "t-i ttlisten on TCP/IP sockets as well as Unix domain socketn");
  581. fprintf(stderr, "t-N nprocstset max number of backends (1..%d, default %d)n",
  582. MAXBACKENDS, DEF_MAXBACKENDS);
  583. fprintf(stderr, "t-n ttdon't reinitialize shared memory after abnormal exitn");
  584. fprintf(stderr, "t-o optiontpass 'option' to each backend serversn");
  585. fprintf(stderr, "t-p porttspecify port for postmaster to listen onn");
  586. fprintf(stderr, "t-s ttsend SIGSTOP to all backend servers if one diesn");
  587. exit(1);
  588. }
  589. static int
  590. ServerLoop(void)
  591. {
  592. fd_set readmask,
  593. writemask;
  594. int nSockets;
  595. Dlelem    *curr;
  596. struct timeval now,
  597. later;
  598. struct timezone tz;
  599. gettimeofday(&now, &tz);
  600. nSockets = initMasks(&readmask, &writemask);
  601. #ifdef HAVE_SIGPROCMASK
  602. sigprocmask(0, NULL, &oldsigmask);
  603. sigemptyset(&newsigmask);
  604. sigaddset(&newsigmask, SIGCHLD);
  605. #endif
  606. for (;;)
  607. {
  608. Port    *port;
  609. fd_set rmask,
  610. wmask;
  611. #ifdef HAVE_SIGPROCMASK
  612. sigprocmask(SIG_SETMASK, &oldsigmask, 0);
  613. #else
  614. sigsetmask(orgsigmask);
  615. #endif
  616. memmove((char *) &rmask, (char *) &readmask, sizeof(fd_set));
  617. memmove((char *) &wmask, (char *) &writemask, sizeof(fd_set));
  618. if (select(nSockets, &rmask, &wmask, (fd_set *) NULL,
  619.    (struct timeval *) NULL) < 0)
  620. {
  621. if (errno == EINTR)
  622. continue;
  623. fprintf(stderr, "%s: ServerLoop: select failed: %sn",
  624. progname, strerror(errno));
  625. return STATUS_ERROR;
  626. }
  627. /*
  628.  * Select a random seed at the time of first receiving a request.
  629.  */
  630. while (random_seed == 0)
  631. {
  632. gettimeofday(&later, &tz);
  633. /*
  634.  * We are not sure how much precision is in tv_usec, so we
  635.  * swap the nibbles of 'later' and XOR them with 'now'. On the
  636.  * off chance that the result is 0, we loop until it isn't.
  637.  */
  638. random_seed = now.tv_usec ^
  639. ((later.tv_usec << 16) |
  640.  ((later.tv_usec >> 16) & 0xffff));
  641. }
  642. /*
  643.  * [TRH] To avoid race conditions, block SIGCHLD signals while we
  644.  * are handling the request. (both reaper() and ConnCreate()
  645.  * manipulate the BackEnd list, and reaper() calls free() which is
  646.  * usually non-reentrant.)
  647.  */
  648. #ifdef HAVE_SIGPROCMASK
  649. sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask);
  650. #else
  651. sigblock(sigmask(SIGCHLD)); /* XXX[TRH] portability */
  652. #endif
  653. /* new connection pending on our well-known port's socket */
  654. #ifndef __CYGWIN32__
  655. if (ServerSock_UNIX != INVALID_SOCK &&
  656. FD_ISSET(ServerSock_UNIX, &rmask) &&
  657. (port = ConnCreate(ServerSock_UNIX)) != NULL)
  658. PacketReceiveSetup(&port->pktInfo,
  659.    readStartupPacket,
  660.    (void *) port);
  661. #endif
  662. if (ServerSock_INET != INVALID_SOCK &&
  663. FD_ISSET(ServerSock_INET, &rmask) &&
  664. (port = ConnCreate(ServerSock_INET)) != NULL)
  665. PacketReceiveSetup(&port->pktInfo,
  666.    readStartupPacket,
  667.    (void *) port);
  668. /* Build up new masks for select(). */
  669. nSockets = initMasks(&readmask, &writemask);
  670. curr = DLGetHead(PortList);
  671. while (curr)
  672. {
  673. Port    *port = (Port *) DLE_VAL(curr);
  674. int status = STATUS_OK;
  675. Dlelem    *next;
  676. if (FD_ISSET(port->sock, &rmask))
  677. {
  678. if (DebugLvl > 1)
  679. fprintf(stderr, "%s: ServerLoop:tthandling reading %dn",
  680. progname, port->sock);
  681. if (PacketReceiveFragment(&port->pktInfo, port->sock) != STATUS_OK)
  682. status = STATUS_ERROR;
  683. }
  684. if (FD_ISSET(port->sock, &wmask))
  685. {
  686. if (DebugLvl > 1)
  687. fprintf(stderr, "%s: ServerLoop:tthandling writing %dn",
  688. progname, port->sock);
  689. if (PacketSendFragment(&port->pktInfo, port->sock) != STATUS_OK)
  690. status = STATUS_ERROR;
  691. }
  692. /* Get this before the connection might be closed. */
  693. next = DLGetSucc(curr);
  694. /*
  695.  * If there is no error and no outstanding data transfer going
  696.  * on, then the authentication handshake must be complete to
  697.  * the postmaster's satisfaction.  So, start the backend.
  698.  */
  699. if (status == STATUS_OK && port->pktInfo.state == Idle)
  700. {
  701. /* Can't start backend if max backend count is exceeded. */
  702. if (CountChildren() >= MaxBackends)
  703. PacketSendError(&port->pktInfo,
  704. "Sorry, too many clients already");
  705. else
  706. {
  707. /*
  708.  * If the backend start fails then keep the connection
  709.  * open to report it.  Otherwise, pretend there is an
  710.  * error to close the connection which will now be
  711.  * managed by the backend.
  712.  */
  713. if (BackendStartup(port) != STATUS_OK)
  714. PacketSendError(&port->pktInfo,
  715. "Backend startup failed");
  716. else
  717. status = STATUS_ERROR;
  718. }
  719. }
  720. /* Close the connection if required. */
  721. if (status != STATUS_OK)
  722. {
  723. StreamClose(port->sock);
  724. DLRemove(curr);
  725. free(port);
  726. DLFreeElem(curr);
  727. }
  728. else
  729. {
  730. /* Set the masks for this connection. */
  731. if (nSockets <= port->sock)
  732. nSockets = port->sock + 1;
  733. if (port->pktInfo.state == WritingPacket)
  734. FD_SET(port->sock, &writemask);
  735. else
  736. FD_SET(port->sock, &readmask);
  737. }
  738. curr = next;
  739. }
  740. }
  741. }
  742. /*
  743.  * Initialise the read and write masks for select() for the well-known ports
  744.  * we are listening on.  Return the number of sockets to listen on.
  745.  */
  746. static int
  747. initMasks(fd_set *rmask, fd_set *wmask)
  748. {
  749. int nsocks = -1;
  750. FD_ZERO(rmask);
  751. FD_ZERO(wmask);
  752. #ifndef __CYGWIN32__
  753. if (ServerSock_UNIX != INVALID_SOCK)
  754. {
  755. FD_SET(ServerSock_UNIX, rmask);
  756. if (ServerSock_UNIX > nsocks)
  757. nsocks = ServerSock_UNIX;
  758. }
  759. #endif
  760. if (ServerSock_INET != INVALID_SOCK)
  761. {
  762. FD_SET(ServerSock_INET, rmask);
  763. if (ServerSock_INET > nsocks)
  764. nsocks = ServerSock_INET;
  765. }
  766. return nsocks + 1;
  767. }
  768. /*
  769.  * Called when the startup packet has been read.
  770.  */
  771. static int
  772. readStartupPacket(void *arg, PacketLen len, void *pkt)
  773. {
  774. Port    *port;
  775. StartupPacket *si;
  776. port = (Port *) arg;
  777. si = (StartupPacket *) pkt;
  778. /*
  779.  * The first field is either a protocol version number or a special
  780.  * request code.
  781.  */
  782. port->proto = ntohl(si->protoVersion);
  783. if (port->proto == CANCEL_REQUEST_CODE)
  784. return processCancelRequest(port, len, pkt);
  785. /* Could add additional special packet types here */
  786. /* Check we can handle the protocol the frontend is using. */
  787. if (PG_PROTOCOL_MAJOR(port->proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
  788. PG_PROTOCOL_MAJOR(port->proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) ||
  789. (PG_PROTOCOL_MAJOR(port->proto) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) &&
  790.  PG_PROTOCOL_MINOR(port->proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
  791. {
  792. PacketSendError(&port->pktInfo, "Unsupported frontend protocol.");
  793. return STATUS_OK; /* don't close the connection yet */
  794. }
  795. /*
  796.  * Get the parameters from the startup packet as C strings.  The
  797.  * packet destination was cleared first so a short packet has zeros
  798.  * silently added and a long packet is silently truncated.
  799.  */
  800. StrNCpy(port->database, si->database, sizeof(port->database) - 1);
  801. StrNCpy(port->user, si->user, sizeof(port->user) - 1);
  802. StrNCpy(port->options, si->options, sizeof(port->options) - 1);
  803. StrNCpy(port->tty, si->tty, sizeof(port->tty) - 1);
  804. /* The database defaults to the user name. */
  805. if (port->database[0] == '')
  806. StrNCpy(port->database, si->user, sizeof(port->database) - 1);
  807. /* Check a user name was given. */
  808. if (port->user[0] == '')
  809. {
  810. PacketSendError(&port->pktInfo,
  811. "No Postgres username specified in startup packet.");
  812. return STATUS_OK; /* don't close the connection yet */
  813. }
  814. /* Start the authentication itself. */
  815. be_recvauth(port);
  816. return STATUS_OK; /* don't close the connection yet */
  817. }
  818. /*
  819.  * The client has sent a cancel request packet, not a normal
  820.  * start-a-new-backend packet. Perform the necessary processing.
  821.  * Note that in any case, we return STATUS_ERROR to close the
  822.  * connection immediately. Nothing is sent back to the client.
  823.  */
  824. static int
  825. processCancelRequest(Port *port, PacketLen len, void *pkt)
  826. {
  827. CancelRequestPacket *canc = (CancelRequestPacket *) pkt;
  828. int backendPID;
  829. long cancelAuthCode;
  830. Dlelem    *curr;
  831. Backend    *bp;
  832. backendPID = (int) ntohl(canc->backendPID);
  833. cancelAuthCode = (long) ntohl(canc->cancelAuthCode);
  834. /* See if we have a matching backend */
  835. for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
  836. {
  837. bp = (Backend *) DLE_VAL(curr);
  838. if (bp->pid == backendPID)
  839. {
  840. if (bp->cancel_key == cancelAuthCode)
  841. {
  842. /* Found a match; signal that backend to cancel current op */
  843. if (DebugLvl)
  844. fprintf(stderr, "%s: processCancelRequest: sending SIGINT to process %dn",
  845. progname, bp->pid);
  846. kill(bp->pid, SIGINT);
  847. }
  848. else
  849. {
  850. /* Right PID, wrong key: no way, Jose */
  851. if (DebugLvl)
  852. fprintf(stderr, "%s: processCancelRequest: bad key in cancel request for process %dn",
  853. progname, bp->pid);
  854. }
  855. return STATUS_ERROR;
  856. }
  857. }
  858. /* No matching backend */
  859. if (DebugLvl)
  860. fprintf(stderr, "%s: processCancelRequest: bad PID in cancel request for process %dn",
  861. progname, backendPID);
  862. return STATUS_ERROR;
  863. }
  864. /*
  865.  * ConnCreate -- create a local connection data structure
  866.  */
  867. static Port *
  868. ConnCreate(int serverFd)
  869. {
  870. Port    *port;
  871. if (!(port = (Port *) calloc(1, sizeof(Port))))
  872. {
  873. fprintf(stderr, "%s: ConnCreate: malloc failedn",
  874. progname);
  875. ExitPostmaster(1);
  876. }
  877. if (StreamConnection(serverFd, port) != STATUS_OK)
  878. {
  879. StreamClose(port->sock);
  880. free(port);
  881. port = NULL;
  882. }
  883. else
  884. {
  885. DLAddHead(PortList, DLNewElem(port));
  886. RandomSalt(port->salt);
  887. port->pktInfo.state = Idle;
  888. }
  889. return port;
  890. }
  891. /*
  892.  * reset_shared -- reset shared memory and semaphores
  893.  */
  894. static void
  895. reset_shared(unsigned short port)
  896. {
  897. ipc_key = port * 1000 + shmem_seq * 100;
  898. CreateSharedMemoryAndSemaphores(ipc_key, MaxBackends);
  899. ActiveBackends = FALSE;
  900. shmem_seq += 1;
  901. if (shmem_seq >= 10)
  902. shmem_seq -= 10;
  903. }
  904. /*
  905.  * pmdie -- signal handler for cleaning up after a kill signal.
  906.  */
  907. static void
  908. pmdie(SIGNAL_ARGS)
  909. {
  910. int i;
  911. TPRINTF(TRACE_VERBOSE, "pmdie %d", postgres_signal_arg);
  912. /*
  913.  * Kill self and/or children processes depending on signal number.
  914.  */
  915. switch (postgres_signal_arg)
  916. {
  917. case SIGHUP:
  918. /* Send SIGHUP to all children (update options flags) */
  919. SignalChildren(SIGHUP);
  920. /* Don't die */
  921. return;
  922. case SIGINT:
  923. /* Die without killing children */
  924. break;
  925. case SIGQUIT:
  926. /* Shutdown all children with SIGTERM */
  927. SignalChildren(SIGTERM);
  928. /* Don't die */
  929. return;
  930. case SIGTERM:
  931. /* Shutdown all children with SIGTERM and SIGKILL, then die */
  932. SignalChildren(SIGTERM);
  933. for (i = 0; i < 10; i++)
  934. {
  935. if (!DLGetHead(BackendList))
  936. break;
  937. sleep(1);
  938. }
  939. if (DLGetHead(BackendList))
  940. SignalChildren(SIGKILL);
  941. break;
  942. case SIGUSR1:
  943. /* Quick die all children with SIGUSR1 and die */
  944. SignalChildren(SIGUSR1);
  945. break;
  946. case SIGUSR2:
  947. /* Send SIGUSR2 to all children (AsyncNotifyHandler) */
  948. SignalChildren(SIGUSR2);
  949. /* Don't die */
  950. return;
  951. }
  952. /* exit postmaster */
  953. proc_exit(0);
  954. }
  955. /*
  956.  * Reaper -- signal handler to cleanup after a backend (child) dies.
  957.  */
  958. static void
  959. reaper(SIGNAL_ARGS)
  960. {
  961. /* GH: replace waitpid for !HAVE_WAITPID. Does this work ? */
  962. #ifdef HAVE_WAITPID
  963. int status; /* backend exit status */
  964. #else
  965. union wait statusp; /* backend exit status */
  966. #endif
  967. int pid; /* process id of dead backend */
  968. if (DebugLvl)
  969. fprintf(stderr, "%s: reaping dead processes...n",
  970. progname);
  971. #ifdef HAVE_WAITPID
  972. while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
  973. {
  974. CleanupProc(pid, status);
  975. pqsignal(SIGCHLD, reaper);
  976. }
  977. #else
  978. while ((pid = wait3(&statusp, WNOHANG, NULL)) > 0)
  979. {
  980. CleanupProc(pid, statusp.w_status);
  981. pqsignal(SIGCHLD, reaper);
  982. }
  983. #endif
  984. }
  985. /*
  986.  * CleanupProc -- cleanup after terminated backend.
  987.  *
  988.  * Remove all local state associated with backend.
  989.  *
  990.  * Dillon's note: should log child's exit status in the system log.
  991.  */
  992. static void
  993. CleanupProc(int pid,
  994. int exitstatus) /* child's exit status. */
  995. {
  996. Dlelem    *prev,
  997.    *curr;
  998. Backend    *bp;
  999. int sig;
  1000. if (DebugLvl)
  1001. {
  1002. fprintf(stderr, "%s: CleanupProc: pid %d exited with status %dn",
  1003. progname, pid, exitstatus);
  1004. }
  1005. /*
  1006.  * If a backend dies in an ugly way (i.e. exit status not 0) then we
  1007.  * must signal all other backends to quickdie. If exit status is zero
  1008.  * we assume everything is hunky dory and simply remove the backend
  1009.  * from the active backend list.
  1010.  */
  1011. if (!exitstatus)
  1012. {
  1013. curr = DLGetHead(BackendList);
  1014. while (curr)
  1015. {
  1016. bp = (Backend *) DLE_VAL(curr);
  1017. if (bp->pid == pid)
  1018. {
  1019. DLRemove(curr);
  1020. free(bp);
  1021. DLFreeElem(curr);
  1022. break;
  1023. }
  1024. curr = DLGetSucc(curr);
  1025. }
  1026. ProcRemove(pid);
  1027. return;
  1028. }
  1029. curr = DLGetHead(BackendList);
  1030. while (curr)
  1031. {
  1032. bp = (Backend *) DLE_VAL(curr);
  1033. /* -----------------
  1034.  * SIGUSR1 is the special signal that says exit
  1035.  * without proc_exit and let the user know what's going on.
  1036.  * ProcSemaphoreKill() cleans up the backends semaphore.  If
  1037.  * SendStop is set (-s on command line), then we send a SIGSTOP so
  1038.  * that we can core dumps from all backends by hand.
  1039.  * -----------------
  1040.  */
  1041. sig = (SendStop) ? SIGSTOP : SIGUSR1;
  1042. if (bp->pid != pid)
  1043. {
  1044. if (DebugLvl)
  1045. fprintf(stderr, "%s: CleanupProc: sending %s to process %dn",
  1046. progname,
  1047. (sig == SIGUSR1)
  1048. ? "SIGUSR1" : "SIGSTOP",
  1049. bp->pid);
  1050. kill(bp->pid, sig);
  1051. }
  1052. ProcRemove(bp->pid);
  1053. prev = DLGetPred(curr);
  1054. DLRemove(curr);
  1055. free(bp);
  1056. DLFreeElem(curr);
  1057. if (!prev)
  1058. { /* removed head */
  1059. curr = DLGetHead(BackendList);
  1060. continue;
  1061. }
  1062. curr = DLGetSucc(prev);
  1063. }
  1064. /*
  1065.  * Nothing up my sleeve here, ActiveBackends means that since the last
  1066.  * time we recreated shared memory and sems another frontend has
  1067.  * requested and received a connection and I have forked off another
  1068.  * backend.  This prevents me from reinitializing shared stuff more
  1069.  * than once for the set of backends that caused the failure and were
  1070.  * killed off.
  1071.  */
  1072. if (ActiveBackends == TRUE && Reinit)
  1073. {
  1074. if (DebugLvl)
  1075. fprintf(stderr, "%s: CleanupProc: reinitializing shared memory and semaphoresn",
  1076. progname);
  1077. shmem_exit(0);
  1078. reset_shared(PostPortName);
  1079. }
  1080. }
  1081. /*
  1082.  * Send a signal to all chidren processes.
  1083.  */
  1084. static void
  1085. SignalChildren(int signal)
  1086. {
  1087. Dlelem    *curr,
  1088.    *next;
  1089. Backend    *bp;
  1090. int mypid = getpid();
  1091. curr = DLGetHead(BackendList);
  1092. while (curr)
  1093. {
  1094. next = DLGetSucc(curr);
  1095. bp = (Backend *) DLE_VAL(curr);
  1096. if (bp->pid != mypid)
  1097. {
  1098. TPRINTF(TRACE_VERBOSE,
  1099. "SignalChildren: sending signal %d to process %d",
  1100. signal, bp->pid);
  1101. kill(bp->pid, signal);
  1102. }
  1103. curr = next;
  1104. }
  1105. }
  1106. /*
  1107.  * BackendStartup -- start backend process
  1108.  *
  1109.  * returns: STATUS_ERROR if the fork/exec failed, STATUS_OK
  1110.  * otherwise.
  1111.  *
  1112.  */
  1113. static int
  1114. BackendStartup(Port *port)
  1115. {
  1116. Backend    *bn; /* for backend cleanup */
  1117. int pid,
  1118. i;
  1119. #ifdef CYR_RECODE
  1120. #define NR_ENVIRONMENT_VBL 6
  1121. char ChTable[80];
  1122. #else
  1123. #define NR_ENVIRONMENT_VBL 5
  1124. #endif
  1125. static char envEntry[NR_ENVIRONMENT_VBL][2 * ARGV_SIZE];
  1126. for (i = 0; i < NR_ENVIRONMENT_VBL; ++i)
  1127. MemSet(envEntry[i], 0, 2 * ARGV_SIZE);
  1128. /*
  1129.  * Set up the necessary environment variables for the backend This
  1130.  * should really be some sort of message....
  1131.  */
  1132. sprintf(envEntry[0], "POSTPORT=%d", PostPortName);
  1133. putenv(envEntry[0]);
  1134. sprintf(envEntry[1], "POSTID=%d", NextBackendTag);
  1135. putenv(envEntry[1]);
  1136. sprintf(envEntry[2], "PG_USER=%s", port->user);
  1137. putenv(envEntry[2]);
  1138. if (!getenv("PGDATA"))
  1139. {
  1140. sprintf(envEntry[3], "PGDATA=%s", DataDir);
  1141. putenv(envEntry[3]);
  1142. }
  1143. sprintf(envEntry[4], "IPC_KEY=%d", ipc_key);
  1144. putenv(envEntry[4]);
  1145. #ifdef CYR_RECODE
  1146. GetCharSetByHost(ChTable, port->raddr.in.sin_addr.s_addr, DataDir);
  1147. if (*ChTable != '')
  1148. {
  1149. sprintf(envEntry[5], "PG_RECODETABLE=%s", ChTable);
  1150. putenv(envEntry[5]);
  1151. }
  1152. #endif
  1153. /*
  1154.  * Compute the cancel key that will be assigned to this backend. The
  1155.  * backend will have its own copy in the forked-off process' value of
  1156.  * MyCancelKey, so that it can transmit the key to the frontend.
  1157.  */
  1158. MyCancelKey = PostmasterRandom();
  1159. if (DebugLvl > 2)
  1160. {
  1161. char   **p;
  1162. extern char **environ;
  1163. fprintf(stderr, "%s: BackendStartup: environ dump:n",
  1164. progname);
  1165. fprintf(stderr, "-----------------------------------------n");
  1166. for (p = environ; *p; ++p)
  1167. fprintf(stderr, "t%sn", *p);
  1168. fprintf(stderr, "-----------------------------------------n");
  1169. }
  1170. /*
  1171.  * Flush stdio channels just before fork, to avoid double-output
  1172.  * problems. Ideally we'd use fflush(NULL) here, but there are still a
  1173.  * few non-ANSI stdio libraries out there (like SunOS 4.1.x) that
  1174.  * coredump if we do. Presently stdout and stderr are the only stdio
  1175.  * output channels used by the postmaster, so fflush'ing them should
  1176.  * be sufficient.
  1177.  */
  1178. fflush(stdout);
  1179. fflush(stderr);
  1180. if ((pid = fork()) == 0)
  1181. { /* child */
  1182. if (DoBackend(port))
  1183. {
  1184. fprintf(stderr, "%s child[%d]: BackendStartup: backend startup failedn",
  1185. progname, (int) getpid());
  1186. exit(1);
  1187. }
  1188. else
  1189. exit(0);
  1190. }
  1191. /* in parent */
  1192. if (pid < 0)
  1193. {
  1194. fprintf(stderr, "%s: BackendStartup: fork failed: %sn",
  1195. progname, strerror(errno));
  1196. return STATUS_ERROR;
  1197. }
  1198. if (DebugLvl)
  1199. fprintf(stderr, "%s: BackendStartup: pid %d user %s db %s socket %dn",
  1200. progname, pid, port->user, port->database,
  1201. port->sock);
  1202. /* Generate a new backend tag for every backend we start */
  1203. /*
  1204.  * XXX theoretically this could wrap around, if you have the patience
  1205.  * to start 2^31 backends ...
  1206.  */
  1207. NextBackendTag -= 1;
  1208. /*
  1209.  * Everything's been successful, it's safe to add this backend to our
  1210.  * list of backends.
  1211.  */
  1212. if (!(bn = (Backend *) calloc(1, sizeof(Backend))))
  1213. {
  1214. fprintf(stderr, "%s: BackendStartup: malloc failedn",
  1215. progname);
  1216. ExitPostmaster(1);
  1217. }
  1218. bn->pid = pid;
  1219. bn->cancel_key = MyCancelKey;
  1220. DLAddHead(BackendList, DLNewElem(bn));
  1221. ActiveBackends = TRUE;
  1222. return STATUS_OK;
  1223. }
  1224. /*
  1225.  * split_opts -- split a string of options and append it to an argv array
  1226.  *
  1227.  * NB: the string is destructively modified!
  1228.  *
  1229.  * Since no current POSTGRES arguments require any quoting characters,
  1230.  * we can use the simple-minded tactic of assuming each set of space-
  1231.  * delimited characters is a separate argv element.
  1232.  *
  1233.  * If you don't like that, well, we *used* to pass the whole option string
  1234.  * as ONE argument to execl(), which was even less intelligent...
  1235.  */
  1236. static void
  1237. split_opts(char **argv, int *argcp, char *s)
  1238. {
  1239. int i = *argcp;
  1240. while (s && *s)
  1241. {
  1242. while (isspace(*s))
  1243. ++s;
  1244. if (*s == '')
  1245. break;
  1246. argv[i++] = s;
  1247. while (*s && !isspace(*s))
  1248. ++s;
  1249. if (*s)
  1250. *s++ = '';
  1251. }
  1252. *argcp = i;
  1253. }
  1254. /*
  1255.  * DoBackend -- set up the backend's argument list and invoke backend main().
  1256.  *
  1257.  * This used to perform an execv() but we no longer exec the backend;
  1258.  * it's the same executable as the postmaster.
  1259.  *
  1260.  * returns:
  1261.  * Shouldn't return at all.
  1262.  * If PostgresMain() fails, return status.
  1263.  */
  1264. static int
  1265. DoBackend(Port *port)
  1266. {
  1267. char    *av[ARGV_SIZE * 2];
  1268. int ac = 0;
  1269. char execbuf[MAXPATHLEN];
  1270. char debugbuf[ARGV_SIZE];
  1271. char protobuf[ARGV_SIZE];
  1272. char dbbuf[ARGV_SIZE];
  1273. char optbuf[ARGV_SIZE];
  1274. char ttybuf[ARGV_SIZE];
  1275. int i;
  1276. struct timeval now;
  1277. struct timezone tz;
  1278. /*
  1279.  * Let's clean up ourselves as the postmaster child
  1280.  */
  1281. /* We don't want the postmaster's proc_exit() handlers */
  1282. on_exit_reset();
  1283. /* ----------------
  1284.  * register signal handlers.
  1285.  * Thanks to the postmaster, these are currently blocked.
  1286.  * ----------------
  1287.  */
  1288. pqsignal(SIGINT, die);
  1289. pqsignal(SIGHUP, die);
  1290. pqsignal(SIGTERM, die);
  1291. pqsignal(SIGPIPE, die);
  1292. pqsignal(SIGUSR1, quickdie);
  1293. pqsignal(SIGUSR2, Async_NotifyHandler);
  1294. pqsignal(SIGFPE, FloatExceptionHandler);
  1295. pqsignal(SIGCHLD, SIG_DFL);
  1296. pqsignal(SIGTTIN, SIG_DFL);
  1297. pqsignal(SIGTTOU, SIG_DFL);
  1298. pqsignal(SIGCONT, SIG_DFL);
  1299. /* OK, let's unblock our signals, all together now... */
  1300. sigprocmask(SIG_SETMASK, &oldsigmask, 0);
  1301. /* Close the postmaster sockets */
  1302. if (NetServer)
  1303. StreamClose(ServerSock_INET);
  1304. #ifndef __CYGWIN32__
  1305. StreamClose(ServerSock_UNIX);
  1306. #endif
  1307. /* Save port etc. for ps status */
  1308. MyProcPort = port;
  1309. MyProcPid = getpid();
  1310. /*
  1311.  * Don't want backend to be able to see the postmaster random number
  1312.  * generator state.  We have to clobber the static random_seed *and*
  1313.  * start a new random sequence in the random() library function.
  1314.  */
  1315. random_seed = 0;
  1316. gettimeofday(&now, &tz);
  1317. srandom(now.tv_usec);
  1318. /* ----------------
  1319.  * Now, build the argv vector that will be given to PostgresMain.
  1320.  *
  1321.  * The layout of the command line is
  1322.  * postgres [secure switches] -p databasename [insecure switches]
  1323.  * where the switches after -p come from the client request.
  1324.  * ----------------
  1325.  */
  1326. StrNCpy(execbuf, Execfile, MAXPATHLEN);
  1327. av[ac++] = execbuf;
  1328. /*
  1329.  * We need to set our argv[0] to an absolute path name because some
  1330.  * OS's use this for dynamic loading, like BSDI.  Without it, when we
  1331.  * change directories to the database dir, the dynamic loader can't
  1332.  * find the base executable and fails. Another advantage is that this
  1333.  * changes the 'ps' displayed process name on some platforms.  It does
  1334.  * on BSDI.  That's a big win.
  1335.  */
  1336. #ifndef linux
  1337. /*
  1338.  * This doesn't work on linux and overwrites the only valid pointer to
  1339.  * the argv buffer.  See PS_INIT_STATUS macro.
  1340.  */
  1341. real_argv[0] = Execfile;
  1342. #endif
  1343. /*
  1344.  * Pass the requested debugging level along to the backend.  We
  1345.  * decrement by one; level one debugging in the postmaster traces
  1346.  * postmaster connection activity, and levels two and higher are
  1347.  * passed along to the backend.  This allows us to watch only the
  1348.  * postmaster or the postmaster and the backend.
  1349.  */
  1350. if (DebugLvl > 1)
  1351. {
  1352. sprintf(debugbuf, "-d%d", DebugLvl);
  1353. av[ac++] = debugbuf;
  1354. }
  1355. /*
  1356.  * Pass any backend switches specified with -o in the postmaster's own
  1357.  * command line.  We assume these are secure. (It's OK to mangle
  1358.  * ExtraOptions since we are now in the child process; this won't
  1359.  * change the postmaster's copy.)
  1360.  */
  1361. split_opts(av, &ac, ExtraOptions);
  1362. /* Tell the backend what protocol the frontend is using. */
  1363. sprintf(protobuf, "-v%u", port->proto);
  1364. av[ac++] = protobuf;
  1365. /*
  1366.  * Tell the backend it is being called from the postmaster, and which
  1367.  * database to use.  -p marks the end of secure switches.
  1368.  */
  1369. av[ac++] = "-p";
  1370. StrNCpy(dbbuf, port->database, ARGV_SIZE);
  1371. av[ac++] = dbbuf;
  1372. /*
  1373.  * Pass the (insecure) option switches from the connection request.
  1374.  */
  1375. StrNCpy(optbuf, port->options, ARGV_SIZE);
  1376. split_opts(av, &ac, optbuf);
  1377. /*
  1378.  * Pass the (insecure) debug output file request.
  1379.  *
  1380.  * NOTE: currently, this is useless code, since the backend will not
  1381.  * honor an insecure -o switch.  I left it here since the backend
  1382.  * could be modified to allow insecure -o, given adequate checking
  1383.  * that the specified filename is something safe to write on.
  1384.  */
  1385. if (port->tty[0])
  1386. {
  1387. StrNCpy(ttybuf, port->tty, ARGV_SIZE);
  1388. av[ac++] = "-o";
  1389. av[ac++] = ttybuf;
  1390. }
  1391. av[ac] = (char *) NULL;
  1392. if (DebugLvl > 1)
  1393. {
  1394. fprintf(stderr, "%s child[%d]: starting with (",
  1395. progname, MyProcPid);
  1396. for (i = 0; i < ac; ++i)
  1397. fprintf(stderr, "%s ", av[i]);
  1398. fprintf(stderr, ")n");
  1399. }
  1400. return (PostgresMain(ac, av, real_argc, real_argv));
  1401. }
  1402. /*
  1403.  * ExitPostmaster -- cleanup
  1404.  */
  1405. static void
  1406. ExitPostmaster(int status)
  1407. {
  1408. /* should cleanup shared memory and kill all backends */
  1409. /*
  1410.  * Not sure of the semantics here. When the Postmaster dies, should
  1411.  * the backends all be killed? probably not.
  1412.  */
  1413. if (ServerSock_INET != INVALID_SOCK)
  1414. StreamClose(ServerSock_INET);
  1415. #ifndef __CYGWIN32__
  1416. if (ServerSock_UNIX != INVALID_SOCK)
  1417. StreamClose(ServerSock_UNIX);
  1418. #endif
  1419. proc_exit(status);
  1420. }
  1421. static void
  1422. dumpstatus(SIGNAL_ARGS)
  1423. {
  1424. Dlelem    *curr = DLGetHead(PortList);
  1425. while (curr)
  1426. {
  1427. Port    *port = DLE_VAL(curr);
  1428. fprintf(stderr, "%s: dumpstatus:n", progname);
  1429. fprintf(stderr, "tsock %dn", port->sock);
  1430. curr = DLGetSucc(curr);
  1431. }
  1432. }
  1433. /*
  1434.  * CharRemap
  1435.  */
  1436. static char
  1437. CharRemap(long int ch)
  1438. {
  1439. if (ch < 0)
  1440. ch = -ch;
  1441. ch = ch % 62;
  1442. if (ch < 26)
  1443. return 'A' + ch;
  1444. ch -= 26;
  1445. if (ch < 26)
  1446. return 'a' + ch;
  1447. ch -= 26;
  1448. return '0' + ch;
  1449. }
  1450. /*
  1451.  * RandomSalt
  1452.  */
  1453. static void
  1454. RandomSalt(char *salt)
  1455. {
  1456. long rand = PostmasterRandom();
  1457. *salt = CharRemap(rand % 62);
  1458. *(salt + 1) = CharRemap(rand / 62);
  1459. }
  1460. /*
  1461.  * PostmasterRandom
  1462.  */
  1463. static long
  1464. PostmasterRandom(void)
  1465. {
  1466. static bool initialized = false;
  1467. if (!initialized)
  1468. {
  1469. Assert(random_seed != 0 && !IsUnderPostmaster);
  1470. srandom(random_seed);
  1471. initialized = true;
  1472. }
  1473. return random() ^ random_seed;
  1474. }
  1475. /*
  1476.  * Count up number of child processes.
  1477.  */
  1478. static int
  1479. CountChildren(void)
  1480. {
  1481. Dlelem    *curr;
  1482. Backend    *bp;
  1483. int mypid = getpid();
  1484. int cnt = 0;
  1485. for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
  1486. {
  1487. bp = (Backend *) DLE_VAL(curr);
  1488. if (bp->pid != mypid)
  1489. cnt++;
  1490. }
  1491. return cnt;
  1492. }