Fix reset query stuck problem.
authorTatsuo Ishii <ishii@postgresql.org>
Fri, 18 Jul 2014 07:37:56 +0000 (16:37 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Fri, 18 Jul 2014 08:00:27 +0000 (17:00 +0900)
It is reported that reset query (DISCARD ALL etc.) occasionally does
not finish and pgpool child remain waiting for reply from backend thus
client cannot connect to pgpool (for example
http://www.pgpool.net/mantisbt/view.php?id=107).  The cause of problem
is not identified yet but if client suddenly closes connection to
pgpool in the middle of query processing, backend may not accept the
reset queries because they are not ready for query.

The fix is, if frontend closes connection in unexpected way, query
process loop immediately returns with new state:
POOL_END_WITH_FRONTEND_ERROR and pgpool closes connection to
PostgreSQL then goes back to new connection request waiting loop.

child.c
pool.h
pool_proto_modules.c

diff --git a/child.c b/child.c
index 63f9897197c46345095c24301c03518997038527..c7b15abb11cf228a5d5baec861c1aa323ec27807 100644 (file)
--- a/child.c
+++ b/child.c
@@ -384,12 +384,15 @@ void do_child(int unix_fd, int inet_fd)
                        {
                                /* client exits */
                                case POOL_END:
+                               case POOL_END_WITH_FRONTEND_ERROR:
                                        /*
                                         * do not cache connection if:
+                                        * frontend abnormally exits or
                                         * pool_config->connection_cahe == 0 or
                                         * database name is template0, template1, postgres or regression
                                         */
-                                       if (pool_config->connection_cache == 0 ||
+                                       if (status == POOL_END_WITH_FRONTEND_ERROR ||
+                                               pool_config->connection_cache == 0 ||
                                                !strcmp(sp->database, "template0") ||
                                                !strcmp(sp->database, "template1") ||
                                                !strcmp(sp->database, "postgres") ||
diff --git a/pool.h b/pool.h
index afc088c21679cfd3967b19cb12231f53efb64711..e772d24543697ad268e2ea9a0c345f310c9fb4d0 100644 (file)
--- a/pool.h
+++ b/pool.h
@@ -6,7 +6,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2012     PgPool Global Development Group
+ * Copyright (c) 2003-2014     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -78,6 +78,7 @@ typedef enum {
        POOL_CONTINUE = 0,
        POOL_IDLE,
        POOL_END,
+       POOL_END_WITH_FRONTEND_ERROR,
        POOL_ERROR,
        POOL_FATAL,
        POOL_DEADLOCK
index c82173f1ca5dde703de0f312c4908363ceb51622..69aca1cb960bdfe407f3afe246e9cd2d0aceb153 100644 (file)
@@ -2184,7 +2184,7 @@ POOL_STATUS ProcessFrontendResponse(POOL_CONNECTION *frontend,
        if (pool_read(frontend, &fkind, 1) < 0)
        {
                pool_log("ProcessFrontendResponse: failed to read kind from frontend. frontend abnormally exited");
-               return POOL_END;
+               return POOL_END_WITH_FRONTEND_ERROR;
        }
 
        pool_debug("ProcessFrontendResponse: kind from frontend %c(%02x)", fkind, fkind);