#include "pool.h"
#include <sys/types.h>
+#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <netdb.h>
#include <arpa/inet.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
#include <sys/stat.h>
#include <fcntl.h>
static void myexit(int code);
static void failover(int sig);
static void reaper(void);
+static int pool_pause(struct timeval *timeout);
+static void pool_sleep(unsigned int second);
static RETSIGTYPE exit_handler(int sig);
static RETSIGTYPE reap_handler(int sig);
static int switch_over_sig = SIGUSR1; /* switch over signal default value */
static int health_check_timer_expired; /* non 0 if health check timer expired */
-static volatile int failover_request = 0;
-static volatile int sigchld_request = 0;
+static volatile sig_atomic_t failover_request = 0;
+static volatile sig_atomic_t sigchld_request = 0;
+static int pipe_fds[2]; /* for delivering signals */
int myargc;
char **myargv;
}
/* set up signal handlers */
+ POOL_SETMASK(&BlockSig);
pool_signal(SIGTERM, exit_handler);
pool_signal(SIGINT, exit_handler);
pool_signal(SIGQUIT, exit_handler);
pool_signal(SIGUSR2, failover_handler);
pool_signal(SIGHUP, exit_handler);
+ /* create pipe for delivering event */
+ if (pipe(pipe_fds) < 0)
+ {
+ pool_error("failed to create pipe");
+ myexit(1);
+ }
+
pool_log("pgpool successfully started");
/*
}
sleep_time = pool_config.health_check_period;
- while (sleep_time > 0)
- {
- CHECK_REQUEST;
- sleep_time = sleep(sleep_time);
- }
+ pool_sleep(sleep_time);
}
else
{
- CHECK_REQUEST;
- pause();
+ for (;;)
+ {
+ int r;
+
+ POOL_SETMASK(&UnBlockSig);
+ r = pool_pause(NULL);
+ POOL_SETMASK(&BlockSig);
+ if (r > 0)
+ break;
+ }
}
}
return 0;
*/
static RETSIGTYPE failover_handler(int sig)
{
- failover_request = sig;
+ POOL_SETMASK(&BlockSig);
+ failover_request = 1;
+ write(pipe_fds[1], "\0", 1);
+ POOL_SETMASK(&UnBlockSig);
}
/*
* Process failover request
+ * failover() must be called under protecting signals.
*/
static void failover(int sig)
{
int i;
int replication = 0;
- POOL_SETMASK(&BlockSig);
-
pool_debug("failover_handler called");
/*
if (getpid() != mypid)
{
pool_debug("failover_handler: I am not parent");
- POOL_SETMASK(&UnBlockSig);
return;
}
*/
if (exiting)
{
- POOL_SETMASK(&UnBlockSig);
return;
}
*/
if (switching)
{
- POOL_SETMASK(&UnBlockSig);
return;
}
switching = 0;
}
- POOL_SETMASK(&UnBlockSig);
}
/*
*/
static RETSIGTYPE reap_handler(int sig)
{
+ POOL_SETMASK(&BlockSig);
sigchld_request = 1;
+ write(pipe_fds[1], "\0", 1);
+ POOL_SETMASK(&UnBlockSig);
}
-
+/*
+ * Attach zombie processes and restart child processes.
+ * reaper() must be called under protecting signals.
+ */
static void reaper(void)
{
pid_t pid;
int status;
int i;
- POOL_SETMASK(&BlockSig);
-
pool_debug("reap_handler called");
sigchld_request = 0;
if (exiting)
{
- POOL_SETMASK(&UnBlockSig);
return;
}
if (switching)
{
- POOL_SETMASK(&UnBlockSig);
return;
}
}
}
}
- POOL_SETMASK(&UnBlockSig);
}
+
+/*
+ * pool_pause: A process pauses by select().
+ */
+static int pool_pause(struct timeval *timeout)
+{
+ fd_set rfds;
+ int n;
+ char dummy;
+
+ FD_ZERO(&rfds);
+ FD_SET(pipe_fds[0], &rfds);
+ n = select(pipe_fds[0]+1, &rfds, NULL, NULL, timeout);
+ if (n == 1)
+ read(pipe_fds[0], &dummy, 1);
+ return n;
+}
+
+/*
+ * pool_pause: A process sleep using pool_pause().
+ * If a signal event occurs, it raises signal handler.
+ */
+static void pool_sleep(unsigned int second)
+{
+ struct timeval current_time, sleep_time;
+
+ gettimeofday(¤t_time, NULL);
+ sleep_time.tv_sec = second + current_time.tv_sec;
+ sleep_time.tv_usec = current_time.tv_usec;
+
+ POOL_SETMASK(&UnBlockSig);
+ while (sleep_time.tv_sec > current_time.tv_sec ||
+ sleep_time.tv_usec > current_time.tv_usec)
+ {
+ struct timeval timeout;
+ int r;
+
+ timeout.tv_sec = sleep_time.tv_sec - current_time.tv_sec;
+ timeout.tv_usec = sleep_time.tv_usec - current_time.tv_usec;
+ if (timeout.tv_usec < 0)
+ {
+ timeout.tv_sec--;
+ timeout.tv_usec += 1000000;
+ }
+
+ r = pool_pause(&timeout);
+ POOL_SETMASK(&BlockSig);
+ if (r > 0)
+ CHECK_REQUEST;
+ POOL_SETMASK(&UnBlockSig);
+ gettimeofday(¤t_time, NULL);
+ }
+ POOL_SETMASK(&BlockSig);
+}