summaryrefslogtreecommitdiff
path: root/src/backend/postmaster/postmaster.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/postmaster/postmaster.c')
-rw-r--r--src/backend/postmaster/postmaster.c121
1 files changed, 106 insertions, 15 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 0525282fd50..6ef32523e79 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.94 1998/08/25 21:04:36 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.95 1998/08/25 21:33:59 scrappy Exp $
*
* NOTES
*
@@ -92,6 +92,7 @@
#include "port-protos.h" /* For gethostname() */
#endif
#include "storage/fd.h"
+#include "utils/trace.h"
#if !defined(MAXINT)
#define MAXINT INT_MAX
@@ -116,6 +117,8 @@ typedef struct bkend
long cancel_key; /* cancel key for cancels for this backend */
} Backend;
+Port *MyBackendPort = NULL;
+
/* list of active backends. For garbage collection only now. */
static Dllist *BackendList;
@@ -232,6 +235,7 @@ static int processCancelRequest(Port *port, PacketLen len, void *pkt);
static int initMasks(fd_set *rmask, fd_set *wmask);
static long PostmasterRandom(void);
static void RandomSalt(char *salt);
+static void SignalChildren(SIGNAL_ARGS);
#ifdef CYR_RECODE
void GetCharSetByHost(char *, int, char *);
@@ -314,16 +318,16 @@ PostmasterMain(int argc, char *argv[])
* We need three params so we can display status. If we don't
* get them from the user, let's make them ourselves.
*/
- if (argc < 4)
+ if (argc < 5)
{
int i;
- char *new_argv[5];
+ char *new_argv[6];
for (i=0; i < argc; i++)
new_argv[i] = argv[i];
- for (; i < 4; i++)
+ for (; i < 5; i++)
new_argv[i] = "";
- new_argv[4] = NULL;
+ new_argv[5] = NULL;
if (!Execfile[0] && FindExec(Execfile, argv[0], "postmaster") < 0)
{
@@ -363,6 +367,7 @@ PostmasterMain(int argc, char *argv[])
hostName = hostbuf;
}
+ MyProcPid = getpid();
DataDir = getenv("PGDATA"); /* default value */
opterr = 0;
@@ -424,6 +429,7 @@ PostmasterMain(int argc, char *argv[])
}
else
DebugLvl = 1;
+ pg_options[TRACE_VERBOSE] = DebugLvl;
break;
case 'i':
NetServer = true;
@@ -535,14 +541,17 @@ PostmasterMain(int argc, char *argv[])
* Set up signal handlers for the postmaster process.
*/
- pqsignal(SIGINT, pmdie);
- pqsignal(SIGCHLD, reaper);
- pqsignal(SIGTTIN, SIG_IGN);
- pqsignal(SIGTTOU, SIG_IGN);
- pqsignal(SIGHUP, pmdie);
- pqsignal(SIGTERM, pmdie);
- pqsignal(SIGCONT, dumpstatus);
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGHUP, pmdie); /* send SIGHUP, don't die */
+ pqsignal(SIGINT, pmdie); /* die */
+ pqsignal(SIGQUIT, pmdie); /* send SIGTERM and die */
+ pqsignal(SIGTERM, pmdie); /* send SIGTERM,SIGKILL and die */
+ pqsignal(SIGPIPE, SIG_IGN); /* ignored */
+ pqsignal(SIGUSR1, pmdie); /* send SIGUSR1 and die */
+ pqsignal(SIGUSR2, pmdie); /* send SIGUSR2, don't die */
+ pqsignal(SIGCHLD, reaper); /* handle child termination */
+ pqsignal(SIGTTIN, SIG_IGN); /* ignored */
+ pqsignal(SIGTTOU, SIG_IGN); /* ignored */
+ pqsignal(SIGWINCH, dumpstatus); /* dump port status */
status = ServerLoop();
@@ -980,6 +989,52 @@ reset_shared(short port)
static void
pmdie(SIGNAL_ARGS)
{
+ int i;
+
+ TPRINTF(TRACE_VERBOSE, "pmdie %d", postgres_signal_arg);
+
+ /*
+ * Kill self and/or children processes depending on signal number.
+ */
+ switch (postgres_signal_arg) {
+ case SIGHUP:
+ /* Send SIGHUP to all children (update options flags) */
+ SignalChildren(SIGHUP);
+ /* Don't die */
+ return;
+ case SIGINT:
+ /* Die without killing children */
+ break;
+ case SIGQUIT:
+ /* Shutdown all children with SIGTERM */
+ SignalChildren(SIGTERM);
+ /* Don't die */
+ return;
+ case SIGTERM:
+ /* Shutdown all children with SIGTERM and SIGKILL, then die */
+ SignalChildren(SIGTERM);
+ for (i=0; i<10; i++) {
+ if (!DLGetHead(BackendList)) {
+ break;
+ }
+ sleep(1);
+ }
+ if (DLGetHead(BackendList)) {
+ SignalChildren(SIGKILL);
+ }
+ break;
+ case SIGUSR1:
+ /* Quick die all children with SIGUSR1 and die */
+ SignalChildren(SIGUSR1);
+ break;
+ case SIGUSR2:
+ /* Send SIGUSR2 to all children (AsyncNotifyHandler) */
+ SignalChildren(SIGUSR2);
+ /* Don't die */
+ return;
+ }
+
+ /* exit postmaster */
proc_exit(0);
}
@@ -1123,6 +1178,35 @@ CleanupProc(int pid,
}
/*
+ * Send a signal to all chidren processes.
+ */
+static void
+SignalChildren(int signal)
+{
+ Dlelem *curr,
+ *next;
+ Backend *bp;
+ int mypid = getpid();
+
+ curr = DLGetHead(BackendList);
+ while (curr)
+ {
+ next = DLGetSucc(curr);
+ bp = (Backend *) DLE_VAL(curr);
+
+ if (bp->pid != mypid)
+ {
+ TPRINTF(TRACE_VERBOSE,
+ "SignalChildren: sending signal %d to process %d",
+ signal, bp->pid);
+ kill(bp->pid, signal);
+ }
+
+ curr = next;
+ }
+}
+
+/*
* BackendStartup -- start backend process
*
* returns: STATUS_ERROR if the fork/exec failed, STATUS_OK
@@ -1342,6 +1426,9 @@ DoBackend(Port *port)
StreamClose(ServerSock_INET);
StreamClose(ServerSock_UNIX);
+ /* Save port for ps status */
+ MyProcPort = port;
+
/*
* Don't want backend to be able to see the postmaster random number
* generator state. We have to clobber the static random_seed *and*
@@ -1368,7 +1455,13 @@ DoBackend(Port *port)
* a big win.
*/
+#ifndef linux
+ /*
+ * This doesn't work on linux and overwrites the only valid
+ * pointer to the argv buffer. See PS_INIT_STATUS macro.
+ */
real_argv[0] = Execfile;
+#endif
/* Tell the backend it is being called from the postmaster */
av[ac++] = "-p";
@@ -1386,8 +1479,6 @@ DoBackend(Port *port)
sprintf(debugbuf, "-d%d", DebugLvl);
av[ac++] = debugbuf;
}
- else
- av[ac++] = "-Q";
/* Pass the requested debugging output file */
if (port->tty[0])