pgpool2.git / summary / log / commit / refs

commit    5b8ef0c235ff93258fc031ddf2ff6d4226c0ce22
Author:   Muhammad Usama <m.usama@gmail.com>
Date:     Wed Nov 18 13:27:25 2015 +0000

    Fixing reset query stuck problem [pgpool-hackers: 1097]
    
    The issue is already fixed in older branches by the
    commit id "cb735f22441001b6afdbb5bac72808db66094ca9", and this fix adopts the
    same solution used by 3.3 branch, i.e. closing the backend connection
    when client idle limit is reached.


src/include/utils/elog.h | 6 ++++++ src/protocol/child.c | 42 +++++++++++++++++++++------------------ src/protocol/pool_process_query.c | 6 +++--- src/utils/error/elog.c | 26 ++++++++++++++++++++++-- 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index fd7ab1df7..163f39522 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -118,6 +118,10 @@ typedef enum #endif #define FATAL 21 /* fatal error - abort process */ #define PANIC 22 /* take down the other backends with me */ +/* pgpool-II extension. This is same as ERROR but sets the + * do not cache connection flag before transforming to ERROR. + */ +#define FRONTEND_ERROR 23 /* transformed to ERROR at errstart */ /* #define DEBUG DEBUG1 */ /* Backward compatibility with pre-7.3 */ #define POOL_EXIT_SUCCESS 0 /* failure exit and child gets restarted*/ @@ -280,6 +284,7 @@ extern int errposition(int cursorpos); #define pg_unreachable() exit(0) +extern bool getfrontendinvalid(void); extern int geterrcode(void); extern int geterrposition(void); extern int getinternalerrposition(void); @@ -431,6 +436,7 @@ typedef struct ErrorData const char *domain; /* message domain */ const char *context_domain; /* message domain for context message */ int sqlerrcode; /* encoded ERRSTATE */ + bool frontend_invalid;/* true when frontend connection is not valid */ char *pgpool_errcode; /* error code to be sent to client */ char *message; /* primary error message */ char *detail; /* detail error message */ diff --git a/src/protocol/child.c b/src/protocol/child.c index 5809d335c..e39d75671 100644 --- a/src/protocol/child.c +++ b/src/protocol/child.c @@ -86,7 +86,7 @@ static POOL_CONNECTION *get_connection(int front_end_fd, SockAddr *saddr); static POOL_CONNECTION_POOL *get_backend_connection(POOL_CONNECTION *frontend); static StartupPacket *StartupPacketCopy(StartupPacket *sp); static void print_process_status(char *remote_host,char* remote_port); -static bool backend_cleanup(POOL_CONNECTION* volatile *frontend, POOL_CONNECTION_POOL* volatile backend); +static bool backend_cleanup(POOL_CONNECTION* volatile *frontend, POOL_CONNECTION_POOL* volatile backend, bool frontend_invalid); static void free_persisten_db_connection_memory(POOL_CONNECTION_POOL_SLOT *cp); static int choose_db_node_id(char *str); static void child_will_go_down(int code, Datum arg); @@ -208,6 +208,7 @@ void do_child(int *fds) if (sigsetjmp(local_sigjmp_buf, 1) != 0) { POOL_PROCESS_CONTEXT *session; + bool frontend_invalid = getfrontendinvalid(); disable_authentication_timeout(); /* Since not using PG_TRY, must reset error stack by hand */ error_context_stack = NULL; @@ -230,7 +231,7 @@ void do_child(int *fds) if (accepted) connection_count_down(); - backend_cleanup(&child_frontend, backend); + backend_cleanup(&child_frontend, backend, frontend_invalid); session = pool_get_process_context(); @@ -369,7 +370,7 @@ void do_child(int *fds) status = pool_process_query(child_frontend, backend, 0); if(status != POOL_CONTINUE) { - backend_cleanup(&child_frontend, backend); + backend_cleanup(&child_frontend, backend, false); break; } } @@ -412,7 +413,7 @@ void do_child(int *fds) * return true if backend connection is cached */ static bool -backend_cleanup(POOL_CONNECTION* volatile *frontend, POOL_CONNECTION_POOL* volatile backend) +backend_cleanup(POOL_CONNECTION* volatile *frontend, POOL_CONNECTION_POOL* volatile backend, bool frontend_invalid) { StartupPacket *sp; bool cache_connection = false; @@ -424,8 +425,9 @@ backend_cleanup(POOL_CONNECTION* volatile *frontend, POOL_CONNECTION_POOL* volat /* * cach connection if connection cache configuration parameter is enabled + * and frontend connection is not invalid */ - if (sp && pool_config->connection_cache != 0) + if (sp && pool_config->connection_cache != 0 && frontend_invalid == false ) { if (*frontend) { @@ -448,20 +450,22 @@ backend_cleanup(POOL_CONNECTION* volatile *frontend, POOL_CONNECTION_POOL* volat } } - /* - * For those special databases, and when frontend client exits abnormally, - * we don't cache connection to backend. - */ - if ((sp && - (!strcmp(sp->database, "template0") || - !strcmp(sp->database, "template1") || - !strcmp(sp->database, "postgres") || - !strcmp(sp->database, "regression"))) || - (*frontend != NULL && - ((*frontend)->socket_state == POOL_SOCKET_EOF || - (*frontend)->socket_state == POOL_SOCKET_ERROR))) - cache_connection = false; - + if (cache_connection) + { + /* + * For those special databases, and when frontend client exits abnormally, + * we don't cache connection to backend. + */ + if ((sp && + (!strcmp(sp->database, "template0") || + !strcmp(sp->database, "template1") || + !strcmp(sp->database, "postgres") || + !strcmp(sp->database, "regression"))) || + (*frontend != NULL && + ((*frontend)->socket_state == POOL_SOCKET_EOF || + (*frontend)->socket_state == POOL_SOCKET_ERROR))) + cache_connection = false; + } /* * Close frontend connection */ diff --git a/src/protocol/pool_process_query.c b/src/protocol/pool_process_query.c index 9f6c7f6c7..e5c832215 100644 --- a/src/protocol/pool_process_query.c +++ b/src/protocol/pool_process_query.c @@ -4451,7 +4451,7 @@ SELECT_RETRY: if (idle_count > pool_config->client_idle_limit) { - ereport(ERROR, + ereport(FRONTEND_ERROR, (pool_error_code("57000"), errmsg("unable to read data"), errdetail("child connection forced to terminate due to client_idle_limit:%d is reached", @@ -4464,7 +4464,7 @@ SELECT_RETRY: if (idle_count_in_recovery > pool_config->client_idle_limit_in_recovery) { - ereport(ERROR, + ereport(FRONTEND_ERROR, (pool_error_code("57000"), errmsg("unable to read data"), errdetail("child connection forced to terminate due to client_idle_limit_in_recovery:%d is reached",pool_config->client_idle_limit_in_recovery))); @@ -4476,7 +4476,7 @@ SELECT_RETRY: * If we are in recovery and client_idle_limit_in_recovery is -1, then * exit immediately. */ - ereport(ERROR, + ereport(FRONTEND_ERROR, (pool_error_code("57000"), errmsg("connection terminated due to online recovery"), errdetail("child connection forced to terminate due to client_idle_limitis:-1"))); diff --git a/src/utils/error/elog.c b/src/utils/error/elog.c index 85897bd27..5eb10060b 100644 --- a/src/utils/error/elog.c +++ b/src/utils/error/elog.c @@ -220,11 +220,17 @@ errstart(int elevel, const char *filename, int lineno, bool output_to_server; bool output_to_client = false; int i; - + int frontend_invalid = false; /* * Check some cases in which we want to promote an error into a more * severe error. None of this logic applies for non-error messages. */ + if (elevel == FRONTEND_ERROR) + { + frontend_invalid = true; + elevel = ERROR; + } + if (elevel >= ERROR) { /* @@ -325,6 +331,7 @@ errstart(int elevel, const char *filename, int lineno, edata = &errordata[errordata_stack_depth]; MemSet(edata, 0, sizeof(ErrorData)); edata->elevel = elevel; + edata->frontend_invalid = frontend_invalid; edata->output_to_server = output_to_server; edata->output_to_client = output_to_client; if(elevel == FATAL && PG_exception_stack == NULL) /* This is startup failure. Take down main process with it */ @@ -972,6 +979,21 @@ geterrcode(void) return edata->sqlerrcode; } +/* + * getfrontendinvalid --- return the currently frontend_invalid value + * + * This is only intended for use in error callback subroutines, since there + * is no other place outside elog.c where the concept is meaningful. + */ +bool getfrontendinvalid(void) +{ + ErrorData *edata = &errordata[errordata_stack_depth]; + + /* we don't bother incrementing recursion_depth */ + CHECK_STACK_DEPTH(); + + return edata->frontend_invalid; +} /* * geterrposition --- return the currently set error position (0 if none) * @@ -1584,7 +1606,7 @@ write_eventlog(int level, const char *line, int len) if (evtHandle == INVALID_HANDLE_VALUE) { - evtHandle = RegisterEventSource(NULL, event_source ? event_source : "PostgreSQL"); + evtHandle = RegisterEventSource(NULL, event_source ? event_source : "pgpool"); if (evtHandle == NULL) { evtHandle = INVALID_HANDLE_VALUE; [parent: 377b5d473939]