pgpool2.git / summary / log / commit / refs

commit    167e3daf4e5fd8731f4f8bb748fe5fc9134db893
Author:   Yoshiyuki Asaba <y-asaba at pgfoundry.org>
Date:     Thu Jul 26 10:15:45 2007 +0000

    SIGALRM handler didn't safe. Because it called non-reentrant functions.
    We only set a flag in SIGALRM handler. Then we close expired
    connections in safe places.


child.c | 31 +++++++++++++++++++++++++++++-- pool.h | 2 ++ pool_connection_pool.c | 22 +++++++++++++++------- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/child.c b/child.c index c00c6b384..060f69fd0 100644 --- a/child.c +++ b/child.c @@ -210,6 +210,13 @@ void do_child(int unix_fd, int inet_fd) idle = 0; child_idle_sec = 0; + /* check backend timer is expired */ + if (backend_timer_expired) + { + pool_backend_timer(); + backend_timer_expired = 0; + } + /* disable timeout */ pool_disable_timeout(); @@ -577,6 +584,7 @@ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *time { fd_set readmask; int fds; + int save_errno; SockAddr saddr; int fd = 0; @@ -618,6 +626,14 @@ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *time fds = select(Max(unix_fd, inet_fd)+1, &readmask, NULL, NULL, timeoutval); + save_errno = errno; + /* check backend timer is expired */ + if (backend_timer_expired) + { + pool_backend_timer(); + backend_timer_expired = 0; + } + /* * following code fragment computes remaining timeout val in a * portable way. Linux does this automazically but other platforms do not. @@ -650,6 +666,8 @@ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *time #endif } + errno = save_errno; + if (fds == -1) { if (errno == EAGAIN || errno == EINTR) @@ -696,6 +714,15 @@ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *time } afd = accept(fd, (struct sockaddr *)&saddr.addr, &saddr.salen); + + save_errno = errno; + /* check backend timer is expired */ + if (backend_timer_expired) + { + pool_backend_timer(); + backend_timer_expired = 0; + } + errno = save_errno; if (afd < 0) { if (errno == EINTR && *InRecovery) @@ -703,9 +730,9 @@ static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *time /* * "Resource temporarily unavailable" (EAGAIN or EWOULDBLOCK) - * can be silently ignored. + * can be silently ignored. And EINTR can be ignored. */ - if (errno != EAGAIN && errno != EWOULDBLOCK) + if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) pool_error("accept() failed. reason: %s", strerror(errno)); return NULL; } diff --git a/pool.h b/pool.h index 1a7614b6a..7e179af2b 100644 --- a/pool.h +++ b/pool.h @@ -376,6 +376,7 @@ typedef struct { extern pid_t mypid; /* parent pid */ extern POOL_CONFIG *pool_config; /* configuration values */ extern POOL_CONNECTION_POOL *pool_connection_pool; /* connection pool */ +extern volatile sig_atomic_t backend_timer_expired; /* flag for connection closed timer is expired */ extern long int weight_master; /* normalized weight of master (0-RAND_MAX range) */ extern int my_proc_id; /* process table id (!= UNIX's PID) */ extern POOL_SYSTEMDB_CONNECTION_POOL *system_db_info; /* systemdb */ @@ -424,6 +425,7 @@ extern int pool_init_cp(void); extern POOL_CONNECTION_POOL *pool_create_cp(void); extern POOL_CONNECTION_POOL *pool_get_cp(char *user, char *database, int protoMajor, int check_socket); extern void pool_discard_cp(char *user, char *database, int protoMajor); +extern void pool_backend_timer(void); extern POOL_STATUS ErrorResponse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend); diff --git a/pool_connection_pool.c b/pool_connection_pool.c index 1e35d239a..bdb53547d 100644 --- a/pool_connection_pool.c +++ b/pool_connection_pool.c @@ -45,6 +45,7 @@ #include "pool.h" POOL_CONNECTION_POOL *pool_connection_pool; /* connection pool */ +volatile sig_atomic_t backend_timer_expired = 0; /* flag for connection closed timer is expired */ static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int slot); static POOL_CONNECTION_POOL *new_connection(POOL_CONNECTION_POOL *p); @@ -142,7 +143,7 @@ POOL_CONNECTION_POOL *pool_get_cp(char *user, char *database, int protoMajor, in free(CONNECTION_SLOT(p, j)); } info = p->info; - memset(p, 0, sizeof(POOL_CONNECTION_POOL)); + memset(p, 0, sizeof(POOL_CONNECTION_POOL_SLOT)); p->info = info; memset(p->info, 0, sizeof(ConnectionInfo)); return NULL; @@ -307,11 +308,16 @@ void pool_connection_pool_timer(POOL_CONNECTION_POOL *backend) * backend connection close timer handler */ RETSIGTYPE pool_backend_timer_handler(int sig) +{ + backend_timer_expired = 1; +} + +void pool_backend_timer(void) { #define TMINTMAX 0x7fffffff POOL_CONNECTION_POOL *p = pool_connection_pool; - int i, freed = 0; + int i, j; time_t now; time_t nearest = TMINTMAX; ConnectionInfo *info; @@ -332,6 +338,8 @@ RETSIGTYPE pool_backend_timer_handler(int sig) /* timer expire? */ if (MASTER_CONNECTION(p)->closetime) { + int freed = 0; + pool_debug("pool_backend_timer_handler: expire time: %d", MASTER_CONNECTION(p)->closetime+pool_config->connection_life_time); @@ -343,19 +351,19 @@ RETSIGTYPE pool_backend_timer_handler(int sig) pool_send_frontend_exits(p); - for (i=0;i<NUM_BACKENDS;i++) + for (j=0;j<NUM_BACKENDS;j++) { - if (!VALID_BACKEND(i)) + if (!VALID_BACKEND(j)) continue; if (!freed) { - pool_free_startup_packet(CONNECTION_SLOT(p, i)->sp); + pool_free_startup_packet(CONNECTION_SLOT(p, j)->sp); freed = 1; } - pool_close(CONNECTION(p, i)); - free(CONNECTION_SLOT(p, i)); + pool_close(CONNECTION(p, j)); + free(CONNECTION_SLOT(p, j)); } info = p->info; memset(p, 0, sizeof(POOL_CONNECTION_POOL)); [parent: a2b3e6a8e914]