From 545a05a3d282d507b22fbffe07eefd9353058859 Mon Sep 17 00:00:00 2001 From: Yoshiyuki Asaba Date: Wed, 25 Jul 2007 06:42:40 +0000 Subject: [PATCH] Fix hang up and SEGV if Parse message contains a warning statement. SELECT '\''; WARNING: nonstandard use of \' in a string literal If pgpool receives a warning message that is NoticeMessage('N') under the extended query protocol, it reads a next message. --- pool_process_query.c | 87 +++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/pool_process_query.c b/pool_process_query.c index 5ec0f6e..af4ce1f 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -841,30 +841,33 @@ static POOL_STATUS Execute(POOL_CONNECTION *frontend, stmt = lookup_prepared_statement_by_portal(&prepared_list, string); - /* load balance trick */ - if (stmt && load_balance_enabled(backend, stmt->prepared_string)) - start_load_balance(backend); - else if (MASTER_SLAVE) + if (stmt) { - master_slave_was_enabled = 1; - MASTER_SLAVE = 0; - master_slave_dml = 1; - } - else if (REPLICATION && !pool_config.replicate_select && is_select_query(stmt->prepared_string) && !is_sequence_query(stmt->prepared_string)) - { - int i; - - /* save backend connection slots */ - for (i=0;inum;i++) + /* load balance trick */ + if (stmt && load_balance_enabled(backend, stmt->prepared_string)) + start_load_balance(backend); + else if (MASTER_SLAVE) { - slots[i] = backend->slots[i]; + master_slave_was_enabled = 1; + MASTER_SLAVE = 0; + master_slave_dml = 1; } + else if (REPLICATION && !pool_config.replicate_select && is_select_query(stmt->prepared_string) && !is_sequence_query(stmt->prepared_string)) + { + int i; - /* send query to master only. */ - replication_was_enabled = 1; - REPLICATION = 0; - in_load_balance = 1; - select_in_transaction = 1; + /* save backend connection slots */ + for (i=0;inum;i++) + { + slots[i] = backend->slots[i]; + } + + /* send query to master only. */ + replication_was_enabled = 1; + REPLICATION = 0; + in_load_balance = 1; + select_in_transaction = 1; + } } for (i = 0;i < backend->num;i++) @@ -2549,8 +2552,8 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C /* * Check if packet kind == 'C'(Command complete), '1'(Parse - * complete), '3'(Close complete). If so, then register or unregister - * pending prepared statement. + * complete), '3'(Close complete). If so, then register or + * unregister pending prepared statement. */ if ((kind == 'C' || kind == '1' || kind == '3') && pending_function && pending_prepared_stmt) @@ -2560,8 +2563,15 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C else if (kind == 'C' && select_in_transaction) select_in_transaction = 0; - pending_function = NULL; - pending_prepared_stmt = NULL; + /* + * Remove a pending function if a received message is not + * NoticeResponse. + */ + if (kind != 'N') + { + pending_function = NULL; + pending_prepared_stmt = NULL; + } status = pool_read(MASTER(backend), &len, sizeof(len)); if (status < 0) @@ -2901,6 +2911,12 @@ POOL_STATUS SimpleForwardToBackend(char kind, POOL_CONNECTION *frontend, POOL_CO break; } + + /* + * Describe message with a portal name receive two messages. + * 1. ParameterDescription + * 2. RowDescriptions or NoData + */ if (kind == 'D' && *p == 'S') { kind1 = pool_read_kind(backend); @@ -2913,14 +2929,25 @@ POOL_STATUS SimpleForwardToBackend(char kind, POOL_CONNECTION *frontend, POOL_CO pool_flush(frontend); } - kind1 = pool_read_kind(backend); - if (kind1 < 0) + for (;;) { - pool_error("SimpleForwardToBackend: pool_read_kind error"); - return POOL_ERROR; + kind1 = pool_read_kind(backend); + if (kind1 < 0) + { + pool_error("SimpleForwardToBackend: pool_read_kind error"); + return POOL_ERROR; + } + SimpleForwardToFrontend(kind1, frontend, backend); + if (pool_flush(frontend) < 0) + return POOL_ERROR; + + /* + * If warning or log messages are received, we must read + * one message from backend. + */ + if (kind1 != 'N') /* Notice Message */ + break; } - SimpleForwardToFrontend(kind1, frontend, backend); - return pool_flush(frontend); } else { -- 2.39.5