pgpool2.git / summary / log / commit / refs

commit    67bc07abd14720ee60b31adccdb4a626095016f7
Author:   Tatsuo Ishii <ishii at sraoss.co.jp>
Date:     Sat Sep 26 07:51:38 2009 +0000

    Fix reset_backend to deal with DEALLOCATE error. In this case prepared
    objects are not removed and reset_backend is infinitely called.
    
    Fix do_command to guard against the case that after execution of an
    SQL command, the backend does not return either N, E or C. This should
    not happen but there was a report that it actually happend in certain
    cases(maybe caused by asynchronized backend data?)
    
    See:
    
    Subject: Re: [Pgpool-general] pgpool 2.2.4: DEALLOCATED children
    From: Xavier Noguer
    Date: Fri, 25 Sep 2009 03:35:57 -0400
    
    For more details.
    
    Patches by Xavier Noguer with minor tweak by Tatsuo Ishii.


pool_process_query.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pool_process_query.c b/pool_process_query.c index 65096699f..97d322655 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -2161,10 +2161,20 @@ static int reset_backend(POOL_CONNECTION_POOL *backend, int qcnt) qn = pool_config->num_reset_queries; + /* + * After execution of all SQL commands in the reset_query_list, we + * remove all prepared objects in the prepared_list. + */ if (qcnt >= qn) { if (prepared_list.cnt == 0) { + /* + * Either no prepared objects were created or DISCARD ALL + * or DEALLOCATE ALL is on the reset_query_list and they + * were executed. The latter causes call to + * reset_prepared_list which removes all prepared objects. + */ reset_prepared_list(&prepared_list); return 2; } @@ -2178,6 +2188,15 @@ static int reset_backend(POOL_CONNECTION_POOL *backend, int qcnt) reset_prepared_list(&prepared_list); return -1; } + /* + * If DEALLOCATE returns ERROR response, instead of + * CommandComplete, del_prepared_list is not called and the + * prepared object keeps on sitting on the prepared list. This + * will cause infinite call to reset_backend. So we call + * del_prepared_list() again. This is harmless since trying to + * remove same prepared object will be ignored. + */ + del_prepared_list(&prepared_list, prepared_list.portal_list[0]); return 1; } @@ -2619,6 +2638,12 @@ static POOL_STATUS do_command(POOL_CONNECTION *frontend, POOL_CONNECTION *backen return POOL_END; } len = ntohl(len) - 4; + + if (kind != 'N' && kind != 'E' && kind != 'C') + { + pool_error("do_command: error, kind is not N, E or C(%02x)", kind); + return POOL_END; + } string = pool_read2(backend, len); if (string == NULL) { [parent: eb4d5638db24]