From 90b22029755121a61812e991838391bd40ba2bbf Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 16 Oct 2003 16:50:41 +0000 Subject: [PATCH] Fix bad interaction between NOTIFY processing and V3 extended query protocol, per report from Igor Shevchenko. NOTIFY thought it could do its thing if transaction blockState is TBLOCK_DEFAULT, but in reality it had better check the low-level transaction state is TRANS_DEFAULT as well. Formerly it was not possible to wait for the client in a state where the first is true and the second is not ... but now we can have such a state. Minor cleanup in StartTransaction() as well. --- src/backend/access/transam/xact.c | 44 +++++++++++++++++++++---------- src/backend/commands/async.c | 8 ++---- src/backend/tcop/postgres.c | 6 ++--- src/include/access/xact.h | 3 ++- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index c7251e9207..e6767d4c4b 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.155 2003/09/28 23:26:20 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.156 2003/10/16 16:50:41 tgl Exp $ * * NOTES * Transaction aborts can now occur two ways: @@ -202,7 +202,7 @@ static TransactionStateData CurrentTransactionStateData = { * perspective */ }; -TransactionState CurrentTransactionState = &CurrentTransactionStateData; +static TransactionState CurrentTransactionState = &CurrentTransactionStateData; /* * User-tweakable parameters @@ -826,20 +826,11 @@ StartTransaction(void) { TransactionState s = CurrentTransactionState; - FreeXactSnapshot(); - XactIsoLevel = DefaultXactIsoLevel; - XactReadOnly = DefaultXactReadOnly; - /* - * Check the current transaction state. If the transaction system is - * switched off, or if we're already in a transaction, do nothing. - * We're already in a transaction when the monitor sends a null - * command to the backend to flush the comm channel. This is a hacky - * fix to a communications problem, and we keep having to deal with it - * here. We should fix the comm channel code. mao 080891 + * check the current transaction state */ - if (s->state == TRANS_INPROGRESS) - return; + if (s->state != TRANS_DEFAULT) + elog(WARNING, "StartTransaction and not in default state"); /* * set the current transaction state information appropriately during @@ -847,6 +838,13 @@ StartTransaction(void) */ s->state = TRANS_START; + /* + * Make sure we've freed any old snapshot, and reset xact state variables + */ + FreeXactSnapshot(); + XactIsoLevel = DefaultXactIsoLevel; + XactReadOnly = DefaultXactReadOnly; + /* * generate a new transaction id */ @@ -1725,6 +1723,24 @@ IsTransactionBlock(void) return true; } +/* + * IsTransactionOrTransactionBlock --- are we within either a transaction + * or a transaction block? (The backend is only really "idle" when this + * returns false.) + * + * This should match up with IsTransactionBlock and IsTransactionState. + */ +bool +IsTransactionOrTransactionBlock(void) +{ + TransactionState s = CurrentTransactionState; + + if (s->blockState == TBLOCK_DEFAULT && s->state == TRANS_DEFAULT) + return false; + + return true; +} + /* * TransactionBlockStatusCode - return status code to send in ReadyForQuery */ diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index d977995f5f..f0dde27bb1 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.101 2003/10/01 21:30:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.102 2003/10/16 16:50:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -91,10 +91,6 @@ #include "utils/syscache.h" -/* stuff that we really ought not be touching directly :-( */ -extern TransactionState CurrentTransactionState; - - /* * State for outbound notifies consists of a list of all relnames NOTIFYed * in the current transaction. We do not actually perform a NOTIFY until @@ -717,7 +713,7 @@ Async_NotifyHandler(SIGNAL_ARGS) void EnableNotifyInterrupt(void) { - if (CurrentTransactionState->blockState != TRANS_DEFAULT) + if (IsTransactionOrTransactionBlock()) return; /* not really idle */ /* diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 9c0af0d238..ea247487e2 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.372 2003/10/09 02:40:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.373 2003/10/16 16:50:41 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -2660,7 +2660,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.372 $ $Date: 2003/10/09 02:40:18 $\n"); + puts("$Revision: 1.373 $ $Date: 2003/10/16 16:50:41 $\n"); } /* @@ -2796,7 +2796,7 @@ PostgresMain(int argc, char *argv[], const char *username) { pgstat_report_tabstat(); - if (IsTransactionBlock()) + if (IsTransactionOrTransactionBlock()) { set_ps_display("idle in transaction"); pgstat_report_activity(" in transaction"); diff --git a/src/include/access/xact.h b/src/include/access/xact.h index 466249feda..d95c3df794 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: xact.h,v 1.56 2003/09/28 23:26:20 tgl Exp $ + * $Id: xact.h,v 1.57 2003/10/16 16:50:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -129,6 +129,7 @@ extern void AbortCurrentTransaction(void); extern void BeginTransactionBlock(void); extern void EndTransactionBlock(void); extern bool IsTransactionBlock(void); +extern bool IsTransactionOrTransactionBlock(void); extern char TransactionBlockStatusCode(void); extern void UserAbortTransactionBlock(void); extern void AbortOutOfAnyTransaction(void); -- GitLab