diff options
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r-- | src/backend/tcop/postgres.c | 80 |
1 files changed, 61 insertions, 19 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index d756b6f2a6c..158b8ee8bcd 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.307.2.1 2003/01/01 21:57:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.307.2.2 2005/06/02 21:04:30 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -92,6 +92,13 @@ static bool EchoQuery = false; /* default don't echo */ */ static volatile bool got_SIGHUP = false; +/* + * Flag to indicate that we are doing the outer loop's read-from-client, + * as opposed to any random read from client that might happen within + * commands like COPY FROM STDIN. + */ +static bool DoingCommandRead = false; + /* ---------------- * people who want to use EOF should #define DONTUSENEWLINE in * tcop/tcopdebug.h @@ -307,6 +314,50 @@ ReadCommand(StringInfo inBuf) return result; } +/* + * prepare_for_client_read -- set up to possibly block on client input + * + * This must be called immediately before any low-level read from the + * client connection. It is necessary to do it at a sufficiently low level + * that there won't be any other operations except the read kernel call + * itself between this call and the subsequent client_read_ended() call. + * In particular there mustn't be use of malloc() or other potentially + * non-reentrant libc functions. This restriction makes it safe for us + * to allow interrupt service routines to execute nontrivial code while + * we are waiting for input. + */ +void +prepare_for_client_read(void) +{ + if (DoingCommandRead) + { + /* Enable immediate processing of asynchronous signals */ + EnableNotifyInterrupt(); + + /* Allow "die" interrupt to be processed while waiting */ + ImmediateInterruptOK = true; + + /* And don't forget to detect one that already arrived */ + QueryCancelPending = false; + CHECK_FOR_INTERRUPTS(); + } +} + +/* + * client_read_ended -- get out of the client-input state + */ +void +client_read_ended(void) +{ + if (DoingCommandRead) + { + ImmediateInterruptOK = false; + QueryCancelPending = false; /* forget any CANCEL signal */ + + DisableNotifyInterrupt(); + } +} + /* * Parse a query string and pass it through the rewriter. @@ -1781,7 +1832,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.307.2.1 $ $Date: 2003/01/01 21:57:18 $\n"); + puts("$Revision: 1.307.2.2 $ $Date: 2005/06/02 21:04:30 $\n"); } /* @@ -1830,6 +1881,7 @@ PostgresMain(int argc, char *argv[], const char *username) CritSectionCount = 0; /* should be unnecessary, but... */ disable_sig_alarm(true); QueryCancelPending = false; /* again in case timeout occurred */ + DoingCommandRead = false; DisableNotifyInterrupt(); debug_query_string = NULL; @@ -1909,20 +1961,13 @@ PostgresMain(int argc, char *argv[], const char *username) } /* - * (2) deal with pending asynchronous NOTIFY from other backends, - * and enable async.c's signal handler to execute NOTIFY directly. - * Then set up other stuff needed before blocking for input. + * (2) Allow asynchronous signals to be executed immediately + * if they come in while we are waiting for client input. + * (This must be conditional since we don't want, say, reads on + * behalf of COPY FROM STDIN doing the same thing.) */ - QueryCancelPending = false; /* forget any earlier CANCEL - * signal */ - - EnableNotifyInterrupt(); - - /* Allow "die" interrupt to be processed while waiting */ - ImmediateInterruptOK = true; - /* and don't forget to detect one that already arrived */ - QueryCancelPending = false; - CHECK_FOR_INTERRUPTS(); + QueryCancelPending = false; /* forget any earlier CANCEL signal */ + DoingCommandRead = true; /* * (3) read a command (loop blocks here) @@ -1932,10 +1977,7 @@ PostgresMain(int argc, char *argv[], const char *username) /* * (4) disable async signal conditions again. */ - ImmediateInterruptOK = false; - QueryCancelPending = false; /* forget any CANCEL signal */ - - DisableNotifyInterrupt(); + DoingCommandRead = false; /* * (5) check for any other interesting events that happened while |