1 /*
2 *
3 * wd_escalation
4 *
5 * pgpool: a language independent connection pool server for PostgreSQL
6 * written by Tatsuo Ishii
7 *
8 * Copyright (c) 2003-2015 PgPool Global Development Group
9 *
10 * Permission to use, copy, modify, and distribute this software and
11 * its documentation for any purpose and without fee is hereby
12 * granted, provided that the above copyright notice appear in all
13 * copies and that both that copyright notice and this permission
14 * notice appear in supporting documentation, and that the name of the
15 * author not be used in advertising or publicity pertaining to
16 * distribution of the software without specific, written prior
17 * permission. The author makes no representations about the
18 * suitability of this software for any purpose. It is provided "as
19 * is" without express or implied warranty.
20 *
21 */
22
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <errno.h>
29
30 #ifdef __FreeBSD__
31 #include <sys/wait.h>
32 #endif
33
34 #include "pool.h"
35 #include "utils/elog.h"
36 #include "utils/palloc.h"
37 #include "utils/memutils.h"
38 #include "pool_config.h"
39 #include "watchdog/wd_utils.h"
40
41 #include "query_cache/pool_memqcache.h"
42
43 static void
wd_exit(int exit_signo)44 wd_exit(int exit_signo)
45 {
46 sigset_t mask;
47
48 sigemptyset(&mask);
49 sigaddset(&mask, SIGTERM);
50 sigaddset(&mask, SIGINT);
51 sigaddset(&mask, SIGQUIT);
52 sigaddset(&mask, SIGCHLD);
53 sigprocmask(SIG_BLOCK, &mask, NULL);
54
55 exit(0);
56 }
57
58 /*
59 * fork escalation process
60 */
61 pid_t
fork_escalation_process(void)62 fork_escalation_process(void)
63 {
64 pid_t pid;
65
66 pid = fork();
67 if (pid != 0)
68 {
69 if (pid == -1)
70 ereport(NOTICE,
71 (errmsg("failed to fork a escalation process")));
72 return pid;
73 }
74 on_exit_reset();
75 processType = PT_WATCHDOG_UTILITY;
76
77 POOL_SETMASK(&UnBlockSig);
78
79 init_ps_display("", "", "", "");
80
81 pool_signal(SIGTERM, wd_exit);
82 pool_signal(SIGINT, wd_exit);
83 pool_signal(SIGQUIT, wd_exit);
84 pool_signal(SIGCHLD, SIG_DFL);
85 pool_signal(SIGHUP, SIG_IGN);
86 pool_signal(SIGPIPE, SIG_IGN);
87
88 MemoryContextSwitchTo(TopMemoryContext);
89
90 set_ps_display("watchdog escalation", false);
91
92 ereport(LOG,
93 (errmsg("watchdog: escalation started")));
94
95 /*
96 * STEP 1 clear shared memory cache
97 */
98 if (pool_config->memory_cache_enabled && pool_is_shmem_cache() &&
99 pool_config->clear_memqcache_on_escalation)
100 {
101 ereport(LOG,
102 (errmsg("watchdog escalation"),
103 errdetail("clearing all the query cache on shared memory")));
104
105 pool_clear_memory_cache();
106 }
107
108 /*
109 * STEP 2 execute escalation command provided by user in pgpool conf file
110 */
111 if (strlen(pool_config->wd_escalation_command))
112 {
113 int r = system(pool_config->wd_escalation_command);
114
115 if (WIFEXITED(r))
116 {
117 if (WEXITSTATUS(r) == EXIT_SUCCESS)
118 ereport(LOG,
119 (errmsg("watchdog escalation successful")));
120 else
121 {
122 ereport(WARNING,
123 (errmsg("watchdog escalation command failed with exit status: %d", WEXITSTATUS(r))));
124 }
125 }
126 else
127 {
128 ereport(WARNING,
129 (errmsg("watchdog escalation command exit abnormally")));
130 }
131 }
132
133 /*
134 * STEP 3 bring up the delegate IP
135 */
136 if (strlen(pool_config->delegate_IP) != 0)
137 {
138 if (wd_IP_up() != WD_OK)
139 ereport(WARNING,
140 (errmsg("watchdog escalation failed to acquire delegate IP")));
141
142 }
143 exit(0);
144 }
145
146 /*
147 * fork de-escalation process
148 */
149 pid_t
fork_plunging_process(void)150 fork_plunging_process(void)
151 {
152 pid_t pid;
153
154 pid = fork();
155 if (pid != 0)
156 {
157 if (pid == -1)
158 ereport(NOTICE,
159 (errmsg("failed to fork a de-escalation process")));
160 return pid;
161 }
162 on_exit_reset();
163 processType = PT_WATCHDOG_UTILITY;
164
165 POOL_SETMASK(&UnBlockSig);
166
167 init_ps_display("", "", "", "");
168
169 pool_signal(SIGTERM, wd_exit);
170 pool_signal(SIGINT, wd_exit);
171 pool_signal(SIGQUIT, wd_exit);
172 pool_signal(SIGCHLD, SIG_DFL);
173 pool_signal(SIGHUP, SIG_IGN);
174 pool_signal(SIGPIPE, SIG_IGN);
175
176 MemoryContextSwitchTo(TopMemoryContext);
177
178 set_ps_display("watchdog de-escalation", false);
179
180 ereport(LOG,
181 (errmsg("watchdog: de-escalation started")));
182
183 /*
184 * STEP 1 execute de-escalation command provided by user in pgpool conf
185 * file
186 */
187 if (strlen(pool_config->wd_de_escalation_command))
188 {
189 int r = system(pool_config->wd_de_escalation_command);
190
191 if (WIFEXITED(r))
192 {
193 if (WEXITSTATUS(r) == EXIT_SUCCESS)
194 ereport(LOG,
195 (errmsg("watchdog de-escalation successful")));
196 else
197 {
198 ereport(WARNING,
199 (errmsg("watchdog de-escalation command failed with exit status: %d", WEXITSTATUS(r))));
200 }
201 }
202 else
203 {
204 ereport(WARNING,
205 (errmsg("watchdog de-escalation command exit abnormally")));
206 }
207 }
208
209 /*
210 * STEP 2 bring down the delegate IP
211 */
212
213 if (strlen(pool_config->delegate_IP) != 0)
214 {
215 if (wd_IP_down() != WD_OK)
216 ereport(WARNING,
217 (errmsg("watchdog de-escalation failed to bring down delegate IP")));
218 }
219 exit(0);
220 }
221