From 1d08611fba84ae9838c6a7414cff98a1206b76a0 Mon Sep 17 00:00:00 2001 From: Yoshiyuki Asaba Date: Thu, 8 May 2008 04:59:26 +0000 Subject: [PATCH] Fix hang up in Execute. We sended a syntax error query to abort a transaction if replicate_select was true. However, the query was sended over Query message. Patch contributed by Kenichi Sawada. --- pool_process_query.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/pool_process_query.c b/pool_process_query.c index d61cc3f..9aac9ae 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -160,6 +160,7 @@ static int master_slave_was_enabled; /* master/slave mode was enabled */ static int internal_transaction_started; /* to issue table lock command a transaction has been started internally */ static int select_in_transaction = 0; /* non 0 if select query is in transaction */ +static int extended_select = 0; /* non 0 if extended mode */ static int in_progress = 0; static void (*pending_function)(PreparedStatementList *p, PreparedStatement *statement) = NULL; @@ -737,6 +738,7 @@ static POOL_STATUS Query(POOL_CONNECTION *frontend, REPLICATION = 0; in_load_balance = 1; select_in_transaction = 1; + extended_select = 0; } /* @@ -891,6 +893,7 @@ static POOL_STATUS Execute(POOL_CONNECTION *frontend, REPLICATION = 0; in_load_balance = 1; select_in_transaction = 1; + extended_select = 1; } } @@ -2815,8 +2818,10 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C pending_function(&prepared_list, pending_prepared_stmt); } else if (kind == 'C' && select_in_transaction) + { select_in_transaction = 0; - + extended_select = 0; + } /* * Remove a pending function if a received message is not * NoticeResponse. @@ -2882,6 +2887,7 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C { int i, k; int res1, res2; + int sync_secondary = 1; char *p1; /* @@ -2919,6 +2925,11 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C do_error_command(SECONDARY(backend), PROTO_MAJOR_V3); } select_in_transaction = 0; + if (extended_select) + { + sync_secondary = 0; + extended_select = 0; + } } for (i = 0;i < backend->num;i++) @@ -2931,6 +2942,20 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C * it by itself. Moreover we do not need it in non-extend mode. * At this point we regard it is not harmfull since error resonse * will not be sent too frequently. + + * We observed a process stall at the synchronous + * point (Line 370 of this code) in this situation: + * 1. replicate_select = false + * 2. do extended select for MASTER, and get some error + * 3. do_error_command for SECONDARY, + * 4. send Sync to both MASTER and SECONDARY + * 5. SECONDARY returns something but MASTER doesn't. + * 6. then pgpool stalls at pool_read on #370 to wait + * for a response from MASTER. + * + * To avoid this situation, we introduced a variable + * 'extended_select' so that pgpool sends Sync only to + * MASTER when the query is in extended mode. */ pool_write(cp, "S", 1); res1 = htonl(4); @@ -2939,7 +2964,7 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C return POOL_END; } - if (!DUAL_MODE) + if (!DUAL_MODE || sync_secondary == 0) break; } -- 2.39.5