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]