pgpool2.git / summary / log / commit / refs

commit    1e0fc2b5f6b769a772ec21eca06b604653fca9a5
Author:   Yoshiyuki Asaba <y-asaba at pgfoundry.org>
Date:     Tue Jul 17 06:04:32 2007 +0000

    Fix hang up when backend node did fast or immediate shutdown.
    
    If shutdown occured, postgres send an error which error code is
    "57P01" and error message is "terminating connection due to
    administrator command".
    
    However, another nodes did not send any messages. pgpool waited for a
    message from them. when the error is sended, pgpool reads the message
    and degenerate.


pool_process_query.c | 90 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/pool_process_query.c b/pool_process_query.c index b3d744d58..981e14523 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -51,6 +51,9 @@ #define INIT_STATEMENT_LIST_SIZE 8 #define DEADLOCK_ERROR_CODE "40P01" +#define ADMIN_SHUTDOWN_ERROR_CODE "57P01" +#define CRASH_SHUTDOWN_ERROR_CODE "57P02" + #define POOL_ERROR_QUERY "send invalid query from pgpool to abort transaction" typedef struct { @@ -196,9 +199,9 @@ static void query_cache_register(char kind, POOL_CONNECTION *frontend, char *dat static POOL_STATUS start_internal_transaction(POOL_CONNECTION_POOL *backend, Node *node); static POOL_STATUS end_internal_transaction(POOL_CONNECTION_POOL *backend); static int extract_ntuples(char *message); -static int detect_error(POOL_CONNECTION *master, char *error_code, int major); +static int detect_error(POOL_CONNECTION *master, char *error_code, int major, bool unread); static int detect_deadlock_error(POOL_CONNECTION *master, int major); - +static int detect_postmaster_down_error(POOL_CONNECTION *master, int major); POOL_STATUS pool_process_query(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, @@ -272,7 +275,7 @@ POOL_STATUS pool_process_query(POOL_CONNECTION *frontend, if (is_cache_empty(frontend, backend)) { struct timeval timeout; - int num_fds; + int num_fds, was_error = 0; timeout.tv_sec = 1; timeout.tv_usec = 0; @@ -321,13 +324,28 @@ POOL_STATUS pool_process_query(POOL_CONNECTION *frontend, return POOL_CONTINUE; } - if (FD_ISSET(MASTER(backend)->fd, &readmask)) + for (i = 0; i < NUM_BACKENDS; i++) { - status = read_kind_from_backend(frontend, backend, &kind); - if (status != POOL_CONTINUE) - return status; + if (VALID_BACKEND(i) && FD_ISSET(CONNECTION(backend, i)->fd, &readmask)) + { + if (detect_postmaster_down_error(CONNECTION(backend, i), MAJOR(backend))) + { + was_error = 1; + notice_backend_error(i); + sleep(5); + break; + } + + status = read_kind_from_backend(frontend, backend, &kind); + if (status != POOL_CONTINUE) + return status; + break; + } } + if (was_error) + continue; + if (!connection_reuse) { if (FD_ISSET(frontend->fd, &exceptmask)) @@ -4787,9 +4805,26 @@ static int extract_ntuples(char *message) return atoi(rows); } -static int detect_deadlock_error(POOL_CONNECTION *master, int major) +static int detect_postmaster_down_error(POOL_CONNECTION *backend, int major) +{ + int r = detect_error(backend, ADMIN_SHUTDOWN_ERROR_CODE, major, false); + if (r) + { + pool_debug("detect_stop_postmaster_error: receive admin shutdown error from a node."); + return r; + } + + r = detect_error(backend, CRASH_SHUTDOWN_ERROR_CODE, major, false); + if (r == 1) + { + pool_debug("detect_stop_postmaster_error: receive crash shutdown error from a node."); + } + return r; +} + +static int detect_deadlock_error(POOL_CONNECTION *backend, int major) { - int r = detect_error(master, DEADLOCK_ERROR_CODE, major); + int r = detect_error(backend, DEADLOCK_ERROR_CODE, major, true); if (r == 1) pool_debug("detect_deadlock_error: receive deadlock error from master node."); return r; @@ -4798,20 +4833,14 @@ static int detect_deadlock_error(POOL_CONNECTION *master, int major) /* * detect_error: Detect specified error from error code. */ -static int detect_error(POOL_CONNECTION *backend, char *error_code, int major) +static int detect_error(POOL_CONNECTION *backend, char *error_code, int major, bool unread) { int is_error = 0; char kind; int readlen = 0, len; - char *buf; + static char buf[1024]; /* memory space is large enough */ char *p, *str; - if ((buf = malloc(1024)) == NULL) - { - pool_error("detect_error: malloc failed"); - return -1; - } - if (pool_read(backend, &kind, sizeof(kind))) return POOL_END; readlen += sizeof(kind); @@ -4836,15 +4865,6 @@ static int detect_error(POOL_CONNECTION *backend, char *error_code, int major) str = malloc(len); pool_read(backend, str, len); readlen += len; - if (readlen > 1024) - { - buf = realloc(buf, readlen); - if (buf == NULL) - { - pool_error("detect_error: malloc failed"); - return -1; - } - } memcpy(p, str, len); /* @@ -4871,20 +4891,14 @@ static int detect_error(POOL_CONNECTION *backend, char *error_code, int major) { str = pool_read_string(backend, &len, 0); readlen += len; - if (readlen > 1024) - { - buf = realloc(buf, readlen); - if (buf == NULL) - { - pool_error("detect_error: malloc failed"); - return -1; - } - } memcpy(p, str, len); } } - if (pool_unread(backend, buf, readlen) != 0) - is_error = -1; - free(buf); + if (unread || !is_error) + { + if (pool_unread(backend, buf, readlen) != 0) + is_error = -1; + } + return is_error; } [parent: e00762684dc0]