Fix single-user mode so that interrupts (particularly SIGTERM and
SIGQUIT) will be recognized and processed while waiting for input, rather than only after something has been typed. Also make SIGQUIT do the same thing as SIGTERM in single-user mode, ie, do a normal shutdown and exit. Since it's relatively easy to provoke SIGQUIT from the keyboard, people may try that instead of control-D, and we'd rather this leads to orderly shutdown. Per report from Leon Mergen and subsequent discussion.
This commit is contained in:
parent
9b619679a8
commit
9e09e3b15e
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.535 2007/06/29 17:07:39 alvherre Exp $
|
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.536 2007/07/09 01:15:14 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* this is the "main" module of the postgres backend and
|
* this is the "main" module of the postgres backend and
|
||||||
@ -164,6 +164,7 @@ static int UseNewLine = 0; /* Use EOF as query delimiters */
|
|||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
static int InteractiveBackend(StringInfo inBuf);
|
static int InteractiveBackend(StringInfo inBuf);
|
||||||
|
static int interactive_getc(void);
|
||||||
static int SocketBackend(StringInfo inBuf);
|
static int SocketBackend(StringInfo inBuf);
|
||||||
static int ReadCommand(StringInfo inBuf);
|
static int ReadCommand(StringInfo inBuf);
|
||||||
static List *pg_rewrite_query(Query *query);
|
static List *pg_rewrite_query(Query *query);
|
||||||
@ -210,15 +211,13 @@ InteractiveBackend(StringInfo inBuf)
|
|||||||
|
|
||||||
resetStringInfo(inBuf);
|
resetStringInfo(inBuf);
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (UseNewLine)
|
if (UseNewLine)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* if we are using \n as a delimiter, then read characters until
|
* if we are using \n as a delimiter, then read characters until
|
||||||
* the \n.
|
* the \n.
|
||||||
*/
|
*/
|
||||||
while ((c = getc(stdin)) != EOF)
|
while ((c = interactive_getc()) != EOF)
|
||||||
{
|
{
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
@ -252,9 +251,10 @@ InteractiveBackend(StringInfo inBuf)
|
|||||||
/*
|
/*
|
||||||
* otherwise read characters until EOF.
|
* otherwise read characters until EOF.
|
||||||
*/
|
*/
|
||||||
while ((c = getc(stdin)) != EOF)
|
while ((c = interactive_getc()) != EOF)
|
||||||
appendStringInfoChar(inBuf, (char) c);
|
appendStringInfoChar(inBuf, (char) c);
|
||||||
|
|
||||||
|
/* No input before EOF signal means time to quit. */
|
||||||
if (inBuf->len == 0)
|
if (inBuf->len == 0)
|
||||||
end = true;
|
end = true;
|
||||||
}
|
}
|
||||||
@ -265,8 +265,6 @@ InteractiveBackend(StringInfo inBuf)
|
|||||||
/*
|
/*
|
||||||
* otherwise we have a user query so process it.
|
* otherwise we have a user query so process it.
|
||||||
*/
|
*/
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add '\0' to make it look the same as message case. */
|
/* Add '\0' to make it look the same as message case. */
|
||||||
appendStringInfoChar(inBuf, (char) '\0');
|
appendStringInfoChar(inBuf, (char) '\0');
|
||||||
@ -281,6 +279,24 @@ InteractiveBackend(StringInfo inBuf)
|
|||||||
return 'Q';
|
return 'Q';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* interactive_getc -- collect one character from stdin
|
||||||
|
*
|
||||||
|
* Even though we are not reading from a "client" process, we still want to
|
||||||
|
* respond to signals, particularly SIGTERM/SIGQUIT. Hence we must use
|
||||||
|
* prepare_for_client_read and client_read_ended.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
interactive_getc(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
prepare_for_client_read();
|
||||||
|
c = getc(stdin);
|
||||||
|
client_read_ended();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* SocketBackend() Is called for frontend-backend connections
|
* SocketBackend() Is called for frontend-backend connections
|
||||||
*
|
*
|
||||||
@ -3092,7 +3108,16 @@ PostgresMain(int argc, char *argv[], const char *username)
|
|||||||
pqsignal(SIGHUP, SigHupHandler); /* set flag to read config file */
|
pqsignal(SIGHUP, SigHupHandler); /* set flag to read config file */
|
||||||
pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */
|
pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */
|
||||||
pqsignal(SIGTERM, die); /* cancel current query and exit */
|
pqsignal(SIGTERM, die); /* cancel current query and exit */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In a standalone backend, SIGQUIT can be generated from the keyboard
|
||||||
|
* easily, while SIGTERM cannot, so we make both signals do die() rather
|
||||||
|
* than quickdie().
|
||||||
|
*/
|
||||||
|
if (IsUnderPostmaster)
|
||||||
pqsignal(SIGQUIT, quickdie); /* hard crash time */
|
pqsignal(SIGQUIT, quickdie); /* hard crash time */
|
||||||
|
else
|
||||||
|
pqsignal(SIGQUIT, die); /* cancel current query and exit */
|
||||||
pqsignal(SIGALRM, handle_sig_alarm); /* timeout conditions */
|
pqsignal(SIGALRM, handle_sig_alarm); /* timeout conditions */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3113,12 +3138,15 @@ PostgresMain(int argc, char *argv[], const char *username)
|
|||||||
|
|
||||||
pqinitmask();
|
pqinitmask();
|
||||||
|
|
||||||
|
if (IsUnderPostmaster)
|
||||||
|
{
|
||||||
/* We allow SIGQUIT (quickdie) at all times */
|
/* We allow SIGQUIT (quickdie) at all times */
|
||||||
#ifdef HAVE_SIGPROCMASK
|
#ifdef HAVE_SIGPROCMASK
|
||||||
sigdelset(&BlockSig, SIGQUIT);
|
sigdelset(&BlockSig, SIGQUIT);
|
||||||
#else
|
#else
|
||||||
BlockSig &= ~(sigmask(SIGQUIT));
|
BlockSig &= ~(sigmask(SIGQUIT));
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
PG_SETMASK(&BlockSig); /* block everything except SIGQUIT */
|
PG_SETMASK(&BlockSig); /* block everything except SIGQUIT */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user