1 /*
2 * PgBouncer - Lightweight connection pooler for PostgreSQL.
3 *
4 * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /*
20 * Launcher for all the rest.
21 */
22
23 #include "bouncer.h"
24
25 #include <usual/signal.h>
26 #include <usual/err.h>
27 #include <usual/cfparser.h>
28 #include <usual/getopt.h>
29 #include <usual/slab.h>
30
31 #ifdef HAVE_SYS_RESOURCE_H
32 #include <sys/resource.h>
33 #endif
34
usage(const char * exe)35 static void usage(const char *exe)
36 {
37 printf("%s is a connection pooler for PostgreSQL.\n\n", exe);
38 printf("Usage:\n");
39 printf(" %s [OPTION]... CONFIG_FILE\n", exe);
40 printf("\nOptions:\n");
41 printf(" -d, --daemon run in background (as a daemon)\n");
42 printf(" -q, --quiet run quietly\n");
43 printf(" -R, --reboot do an online reboot\n");
44 printf(" -u, --user=USERNAME assume identity of USERNAME\n");
45 printf(" -v, --verbose increase verbosity\n");
46 printf(" -V, --version show version, then exit\n");
47 printf(" -h, --help show this help, then exit\n");
48 printf("\n");
49 #ifdef WIN32
50 printf("Windows service registration:\n");
51 printf(" --regservice CONFIG_FILE [-U USERNAME [-P PASSWORD]]\n");
52 printf(" --unregservice CONFIG_FILE\n");
53 printf("\n");
54 #endif
55 printf("Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
56 printf("%s home page: <%s>\n", PACKAGE_NAME, PACKAGE_URL);
57 exit(0);
58 }
59
60 /* global libevent handle */
61 struct event_base *pgb_event_base;
62
63 /* async dns handler */
64 struct DNSContext *adns;
65
66 struct HBA *parsed_hba;
67
68 /*
69 * configuration storage
70 */
71
72 int cf_daemon;
73 int cf_pause_mode = P_NONE;
74 int cf_shutdown; /* 1 - wait for queries to finish, 2 - shutdown immediately */
75 int cf_reboot;
76 static char *cf_username;
77 char *cf_config_file;
78
79 char *cf_listen_addr;
80 int cf_listen_port;
81 int cf_listen_backlog;
82 char *cf_unix_socket_dir;
83 int cf_unix_socket_mode;
84 char *cf_unix_socket_group;
85
86 int cf_pool_mode = POOL_SESSION;
87
88 /* sbuf config */
89 int cf_sbuf_len;
90 int cf_sbuf_loopcnt;
91 int cf_so_reuseport;
92 int cf_tcp_socket_buffer;
93 #if defined(TCP_DEFER_ACCEPT) || defined(SO_ACCEPTFILTER)
94 int cf_tcp_defer_accept = 1;
95 #else
96 int cf_tcp_defer_accept = 0;
97 #endif
98 int cf_tcp_keepalive;
99 int cf_tcp_keepcnt;
100 int cf_tcp_keepidle;
101 int cf_tcp_keepintvl;
102 int cf_tcp_user_timeout;
103
104 int cf_auth_type = AUTH_MD5;
105 char *cf_auth_file;
106 char *cf_auth_hba_file;
107 char *cf_auth_user;
108 char *cf_auth_query;
109
110 int cf_max_client_conn;
111 int cf_default_pool_size;
112 int cf_min_pool_size;
113 int cf_res_pool_size;
114 usec_t cf_res_pool_timeout;
115 int cf_max_db_connections;
116 int cf_max_user_connections;
117
118 char *cf_server_reset_query;
119 int cf_server_reset_query_always;
120 char *cf_server_check_query;
121 usec_t cf_server_check_delay;
122 int cf_server_fast_close;
123 int cf_server_round_robin;
124 int cf_disable_pqexec;
125 usec_t cf_dns_max_ttl;
126 usec_t cf_dns_nxdomain_ttl;
127 usec_t cf_dns_zone_check_period;
128 char *cf_resolv_conf;
129 unsigned int cf_max_packet_size;
130
131 char *cf_ignore_startup_params;
132
133 char *cf_autodb_connstr; /* here is "" different from NULL */
134
135 usec_t cf_autodb_idle_timeout;
136
137 usec_t cf_server_lifetime;
138 usec_t cf_server_idle_timeout;
139 usec_t cf_server_connect_timeout;
140 usec_t cf_server_login_retry;
141 usec_t cf_query_timeout;
142 usec_t cf_query_wait_timeout;
143 usec_t cf_client_idle_timeout;
144 usec_t cf_client_login_timeout;
145 usec_t cf_idle_transaction_timeout;
146 usec_t cf_suspend_timeout;
147
148 usec_t g_suspend_start;
149
150 char *cf_pidfile;
151 char *cf_jobname;
152
153 char *cf_admin_users;
154 char *cf_stats_users;
155 int cf_stats_period;
156 int cf_log_stats;
157
158 int cf_log_connections;
159 int cf_log_disconnections;
160 int cf_log_pooler_errors;
161 int cf_application_name_add_host;
162
163 int cf_client_tls_sslmode;
164 char *cf_client_tls_protocols;
165 char *cf_client_tls_ca_file;
166 char *cf_client_tls_cert_file;
167 char *cf_client_tls_key_file;
168 char *cf_client_tls_ciphers;
169 char *cf_client_tls_dheparams;
170 char *cf_client_tls_ecdhecurve;
171
172 int cf_server_tls_sslmode;
173 char *cf_server_tls_protocols;
174 char *cf_server_tls_ca_file;
175 char *cf_server_tls_cert_file;
176 char *cf_server_tls_key_file;
177 char *cf_server_tls_ciphers;
178
179 /*
180 * config file description
181 */
182
183 static bool set_defer_accept(struct CfValue *cv, const char *val);
184 #define DEFER_OPS {set_defer_accept, cf_get_int}
185
186 static const struct CfLookup auth_type_map[] = {
187 { "any", AUTH_ANY },
188 { "trust", AUTH_TRUST },
189 { "plain", AUTH_PLAIN },
190 { "md5", AUTH_MD5 },
191 { "cert", AUTH_CERT },
192 { "hba", AUTH_HBA },
193 #ifdef HAVE_PAM
194 { "pam", AUTH_PAM },
195 #endif
196 { "scram-sha-256", AUTH_SCRAM_SHA_256 },
197 { NULL }
198 };
199
200 const struct CfLookup pool_mode_map[] = {
201 { "session", POOL_SESSION },
202 { "transaction", POOL_TX },
203 { "statement", POOL_STMT },
204 { NULL }
205 };
206
207 const struct CfLookup sslmode_map[] = {
208 { "disable", SSLMODE_DISABLED },
209 { "allow", SSLMODE_ALLOW },
210 { "prefer", SSLMODE_PREFER },
211 { "require", SSLMODE_REQUIRE },
212 { "verify-ca", SSLMODE_VERIFY_CA },
213 { "verify-full", SSLMODE_VERIFY_FULL },
214 { NULL }
215 };
216
217 /*
218 * Add new parameters in alphabetical order. This order is used by SHOW CONFIG.
219 */
220 static const struct CfKey bouncer_params [] = {
221 CF_ABS("admin_users", CF_STR, cf_admin_users, 0, ""),
222 CF_ABS("application_name_add_host", CF_INT, cf_application_name_add_host, 0, "0"),
223 CF_ABS("auth_file", CF_STR, cf_auth_file, 0, NULL),
224 CF_ABS("auth_hba_file", CF_STR, cf_auth_hba_file, 0, ""),
225 CF_ABS("auth_query", CF_STR, cf_auth_query, 0, "SELECT usename, passwd FROM pg_shadow WHERE usename=$1"),
226 CF_ABS("auth_type", CF_LOOKUP(auth_type_map), cf_auth_type, 0, "md5"),
227 CF_ABS("auth_user", CF_STR, cf_auth_user, 0, NULL),
228 CF_ABS("autodb_idle_timeout", CF_TIME_USEC, cf_autodb_idle_timeout, 0, "3600"),
229 CF_ABS("client_idle_timeout", CF_TIME_USEC, cf_client_idle_timeout, 0, "0"),
230 CF_ABS("client_login_timeout", CF_TIME_USEC, cf_client_login_timeout, 0, "60"),
231 CF_ABS("client_tls_ca_file", CF_STR, cf_client_tls_ca_file, 0, ""),
232 CF_ABS("client_tls_cert_file", CF_STR, cf_client_tls_cert_file, 0, ""),
233 CF_ABS("client_tls_ciphers", CF_STR, cf_client_tls_ciphers, 0, "fast"),
234 CF_ABS("client_tls_dheparams", CF_STR, cf_client_tls_dheparams, 0, "auto"),
235 CF_ABS("client_tls_ecdhcurve", CF_STR, cf_client_tls_ecdhecurve, 0, "auto"),
236 CF_ABS("client_tls_key_file", CF_STR, cf_client_tls_key_file, 0, ""),
237 CF_ABS("client_tls_protocols", CF_STR, cf_client_tls_protocols, 0, "secure"),
238 CF_ABS("client_tls_sslmode", CF_LOOKUP(sslmode_map), cf_client_tls_sslmode, 0, "disable"),
239 CF_ABS("conffile", CF_STR, cf_config_file, 0, NULL),
240 CF_ABS("default_pool_size", CF_INT, cf_default_pool_size, 0, "20"),
241 CF_ABS("disable_pqexec", CF_INT, cf_disable_pqexec, CF_NO_RELOAD, "0"),
242 CF_ABS("dns_max_ttl", CF_TIME_USEC, cf_dns_max_ttl, 0, "15"),
243 CF_ABS("dns_nxdomain_ttl", CF_TIME_USEC, cf_dns_nxdomain_ttl, 0, "15"),
244 CF_ABS("dns_zone_check_period", CF_TIME_USEC, cf_dns_zone_check_period, 0, "0"),
245 CF_ABS("idle_transaction_timeout", CF_TIME_USEC, cf_idle_transaction_timeout, 0, "0"),
246 CF_ABS("ignore_startup_parameters", CF_STR, cf_ignore_startup_params, 0, ""),
247 CF_ABS("job_name", CF_STR, cf_jobname, CF_NO_RELOAD, "pgbouncer"),
248 CF_ABS("listen_addr", CF_STR, cf_listen_addr, CF_NO_RELOAD, ""),
249 CF_ABS("listen_backlog", CF_INT, cf_listen_backlog, CF_NO_RELOAD, "128"),
250 CF_ABS("listen_port", CF_INT, cf_listen_port, CF_NO_RELOAD, "6432"),
251 CF_ABS("log_connections", CF_INT, cf_log_connections, 0, "1"),
252 CF_ABS("log_disconnections", CF_INT, cf_log_disconnections, 0, "1"),
253 CF_ABS("log_pooler_errors", CF_INT, cf_log_pooler_errors, 0, "1"),
254 CF_ABS("log_stats", CF_INT, cf_log_stats, 0, "1"),
255 CF_ABS("logfile", CF_STR, cf_logfile, 0, ""),
256 CF_ABS("max_client_conn", CF_INT, cf_max_client_conn, 0, "100"),
257 CF_ABS("max_db_connections", CF_INT, cf_max_db_connections, 0, "0"),
258 CF_ABS("max_packet_size", CF_UINT, cf_max_packet_size, 0, "2147483647"),
259 CF_ABS("max_user_connections", CF_INT, cf_max_user_connections, 0, "0"),
260 CF_ABS("min_pool_size", CF_INT, cf_min_pool_size, 0, "0"),
261 CF_ABS("pidfile", CF_STR, cf_pidfile, CF_NO_RELOAD, ""),
262 CF_ABS("pkt_buf", CF_INT, cf_sbuf_len, CF_NO_RELOAD, "4096"),
263 CF_ABS("pool_mode", CF_LOOKUP(pool_mode_map), cf_pool_mode, 0, "session"),
264 CF_ABS("query_timeout", CF_TIME_USEC, cf_query_timeout, 0, "0"),
265 CF_ABS("query_wait_timeout", CF_TIME_USEC, cf_query_wait_timeout, 0, "120"),
266 CF_ABS("reserve_pool_size", CF_INT, cf_res_pool_size, 0, "0"),
267 CF_ABS("reserve_pool_timeout", CF_TIME_USEC, cf_res_pool_timeout, 0, "5"),
268 CF_ABS("resolv_conf", CF_STR, cf_resolv_conf, CF_NO_RELOAD, ""),
269 CF_ABS("sbuf_loopcnt", CF_INT, cf_sbuf_loopcnt, 0, "5"),
270 CF_ABS("server_check_delay", CF_TIME_USEC, cf_server_check_delay, 0, "30"),
271 CF_ABS("server_check_query", CF_STR, cf_server_check_query, 0, "select 1"),
272 CF_ABS("server_connect_timeout", CF_TIME_USEC, cf_server_connect_timeout, 0, "15"),
273 CF_ABS("server_fast_close", CF_INT, cf_server_fast_close, 0, "0"),
274 CF_ABS("server_idle_timeout", CF_TIME_USEC, cf_server_idle_timeout, 0, "600"),
275 CF_ABS("server_lifetime", CF_TIME_USEC, cf_server_lifetime, 0, "3600"),
276 CF_ABS("server_login_retry", CF_TIME_USEC, cf_server_login_retry, 0, "15"),
277 CF_ABS("server_reset_query", CF_STR, cf_server_reset_query, 0, "DISCARD ALL"),
278 CF_ABS("server_reset_query_always", CF_INT, cf_server_reset_query_always, 0, "0"),
279 CF_ABS("server_round_robin", CF_INT, cf_server_round_robin, 0, "0"),
280 CF_ABS("server_tls_ca_file", CF_STR, cf_server_tls_ca_file, 0, ""),
281 CF_ABS("server_tls_cert_file", CF_STR, cf_server_tls_cert_file, 0, ""),
282 CF_ABS("server_tls_ciphers", CF_STR, cf_server_tls_ciphers, 0, "fast"),
283 CF_ABS("server_tls_key_file", CF_STR, cf_server_tls_key_file, 0, ""),
284 CF_ABS("server_tls_protocols", CF_STR, cf_server_tls_protocols, 0, "secure"),
285 CF_ABS("server_tls_sslmode", CF_LOOKUP(sslmode_map), cf_server_tls_sslmode, 0, "disable"),
286 #ifdef WIN32
287 CF_ABS("service_name", CF_STR, cf_jobname, CF_NO_RELOAD, NULL), /* alias for job_name */
288 #endif
289 CF_ABS("so_reuseport", CF_INT, cf_so_reuseport, CF_NO_RELOAD, "0"),
290 CF_ABS("stats_period", CF_INT, cf_stats_period, 0, "60"),
291 CF_ABS("stats_users", CF_STR, cf_stats_users, 0, ""),
292 CF_ABS("suspend_timeout", CF_TIME_USEC, cf_suspend_timeout, 0, "10"),
293 CF_ABS("syslog", CF_INT, cf_syslog, 0, "0"),
294 CF_ABS("syslog_facility", CF_STR, cf_syslog_facility, 0, "daemon"),
295 CF_ABS("syslog_ident", CF_STR, cf_syslog_ident, 0, "pgbouncer"),
296 CF_ABS("tcp_defer_accept", DEFER_OPS, cf_tcp_defer_accept, 0, NULL),
297 CF_ABS("tcp_keepalive", CF_INT, cf_tcp_keepalive, 0, "1"),
298 CF_ABS("tcp_keepcnt", CF_INT, cf_tcp_keepcnt, 0, "0"),
299 CF_ABS("tcp_keepidle", CF_INT, cf_tcp_keepidle, 0, "0"),
300 CF_ABS("tcp_keepintvl", CF_INT, cf_tcp_keepintvl, 0, "0"),
301 CF_ABS("tcp_socket_buffer", CF_INT, cf_tcp_socket_buffer, 0, "0"),
302 CF_ABS("tcp_user_timeout", CF_INT, cf_tcp_user_timeout, 0, "0"),
303 CF_ABS("unix_socket_dir", CF_STR, cf_unix_socket_dir, CF_NO_RELOAD, DEFAULT_UNIX_SOCKET_DIR),
304 #ifndef WIN32
305 CF_ABS("unix_socket_group", CF_STR, cf_unix_socket_group, CF_NO_RELOAD, ""),
306 CF_ABS("unix_socket_mode", CF_INT, cf_unix_socket_mode, CF_NO_RELOAD, "0777"),
307 #endif
308 #ifndef WIN32
309 CF_ABS("user", CF_STR, cf_username, CF_NO_RELOAD, NULL),
310 #endif
311 CF_ABS("verbose", CF_INT, cf_verbose, 0, NULL),
312
313 {NULL}
314 };
315
316 static const struct CfSect config_sects [] = {
317 {
318 .sect_name = "pgbouncer",
319 .key_list = bouncer_params,
320 }, {
321 .sect_name = "databases",
322 .set_key = parse_database,
323 }, {
324 .sect_name = "users",
325 .set_key = parse_user,
326 }, {
327 .sect_name = NULL,
328 }
329 };
330
331 static struct CfContext main_config = { config_sects, };
332
set_config_param(const char * key,const char * val)333 bool set_config_param(const char *key, const char *val)
334 {
335 return cf_set(&main_config, "pgbouncer", key, val);
336 }
337
config_for_each(void (* param_cb)(void * arg,const char * name,const char * val,const char * defval,bool reloadable),void * arg)338 void config_for_each(void (*param_cb)(void *arg, const char *name, const char *val, const char *defval, bool reloadable),
339 void *arg)
340 {
341 const struct CfKey *k = bouncer_params;
342 char buf[256];
343 bool reloadable;
344 const char *val;
345 int ro = CF_NO_RELOAD | CF_READONLY;
346
347 for (; k->key_name; k++) {
348 val = cf_get(&main_config, "pgbouncer", k->key_name, buf, sizeof(buf));
349 reloadable = (k->flags & ro) == 0;
350 param_cb(arg, k->key_name, val, k->def_value, reloadable);
351 }
352 }
353
set_defer_accept(struct CfValue * cv,const char * val)354 static bool set_defer_accept(struct CfValue *cv, const char *val)
355 {
356 int *p = cv->value_p;
357 bool ok;
358 int oldval = *p;
359 ok = cf_set_int(cv, val);
360 if (ok && !!oldval != !!*p)
361 pooler_tune_accept(*p);
362 return ok;
363 }
364
set_dbs_dead(bool flag)365 static void set_dbs_dead(bool flag)
366 {
367 struct List *item;
368 PgDatabase *db;
369
370 statlist_for_each(item, &database_list) {
371 db = container_of(item, PgDatabase, head);
372 if (db->admin)
373 continue;
374 if (db->db_auto)
375 continue;
376 db->db_dead = flag;
377 }
378 }
379
380 /* Tells if the specified auth type requires data from the auth file. */
requires_auth_file(int auth_type)381 bool requires_auth_file(int auth_type)
382 {
383 /* For PAM authentication auth file is not used */
384 if (auth_type == AUTH_PAM)
385 return false;
386 return auth_type >= AUTH_TRUST;
387 }
388
389 /* config loading, tries to be tolerant to errors */
load_config(void)390 void load_config(void)
391 {
392 static bool loaded = false;
393 bool ok;
394
395 set_dbs_dead(true);
396
397 /* actual loading */
398 ok = cf_load_file(&main_config, cf_config_file);
399 if (ok) {
400 /* load users if needed */
401 if (requires_auth_file(cf_auth_type))
402 loader_users_check();
403 loaded = true;
404 } else if (!loaded) {
405 die("cannot load config file");
406 } else {
407 log_warning("config file loading failed");
408 /* if ini file missing, don't kill anybody */
409 set_dbs_dead(false);
410 }
411
412 if (cf_auth_type == AUTH_HBA) {
413 struct HBA *hba = hba_load_rules(cf_auth_hba_file);
414 if (hba) {
415 if (parsed_hba)
416 hba_free(parsed_hba);
417 parsed_hba = hba;
418 }
419 }
420
421 /* kill dbs */
422 config_postprocess();
423
424 /* reopen logfile */
425 if (main_config.loaded)
426 reset_logging();
427 }
428
429 /*
430 * signal handling.
431 *
432 * handle_* functions are not actual signal handlers but called from
433 * event_loop() so they have no restrictions what they can do.
434 */
435 static struct event ev_sigterm;
436 static struct event ev_sigint;
437
handle_sigterm(evutil_socket_t sock,short flags,void * arg)438 static void handle_sigterm(evutil_socket_t sock, short flags, void *arg)
439 {
440 log_info("got SIGTERM, fast exit");
441 /* pidfile cleanup happens via atexit() */
442 exit(1);
443 }
444
handle_sigint(evutil_socket_t sock,short flags,void * arg)445 static void handle_sigint(evutil_socket_t sock, short flags, void *arg)
446 {
447 log_info("got SIGINT, shutting down");
448 sd_notify(0, "STOPPING=1");
449 if (cf_reboot)
450 die("takeover was in progress, going down immediately");
451 if (cf_pause_mode == P_SUSPEND)
452 die("suspend was in progress, going down immediately");
453 cf_pause_mode = P_PAUSE;
454 cf_shutdown = 1;
455 }
456
457 #ifndef WIN32
458
459 static struct event ev_sigusr1;
460 static struct event ev_sigusr2;
461 static struct event ev_sighup;
462
handle_sigusr1(int sock,short flags,void * arg)463 static void handle_sigusr1(int sock, short flags, void *arg)
464 {
465 if (cf_pause_mode == P_NONE) {
466 log_info("got SIGUSR1, pausing all activity");
467 cf_pause_mode = P_PAUSE;
468 } else {
469 log_info("got SIGUSR1, but already paused/suspended");
470 }
471 }
472
handle_sigusr2(int sock,short flags,void * arg)473 static void handle_sigusr2(int sock, short flags, void *arg)
474 {
475 switch (cf_pause_mode) {
476 case P_SUSPEND:
477 log_info("got SIGUSR2, continuing from SUSPEND");
478 resume_all();
479 cf_pause_mode = P_NONE;
480 break;
481 case P_PAUSE:
482 log_info("got SIGUSR2, continuing from PAUSE");
483 cf_pause_mode = P_NONE;
484 break;
485 case P_NONE:
486 log_info("got SIGUSR2, but not paused/suspended");
487 }
488
489 /* avoid surprise later if cf_shutdown stays set */
490 if (cf_shutdown) {
491 log_info("canceling shutdown");
492 cf_shutdown = 0;
493 }
494 }
495
handle_sighup(int sock,short flags,void * arg)496 static void handle_sighup(int sock, short flags, void *arg)
497 {
498 log_info("got SIGHUP, re-reading config");
499 sd_notify(0, "RELOADING=1");
500 load_config();
501 if (!sbuf_tls_setup())
502 log_error("TLS configuration could not be reloaded, keeping old configuration");
503 sd_notify(0, "READY=1");
504 }
505 #endif
506
signal_setup(void)507 static void signal_setup(void)
508 {
509 int err;
510
511 #ifndef WIN32
512 sigset_t set;
513
514 /* block SIGPIPE */
515 sigemptyset(&set);
516 sigaddset(&set, SIGPIPE);
517 err = sigprocmask(SIG_BLOCK, &set, NULL);
518 if (err < 0)
519 fatal_perror("sigprocmask");
520
521 /* install handlers */
522
523 evsignal_assign(&ev_sigusr1, pgb_event_base, SIGUSR1, handle_sigusr1, NULL);
524 err = evsignal_add(&ev_sigusr1, NULL);
525 if (err < 0)
526 fatal_perror("evsignal_add");
527
528 evsignal_assign(&ev_sigusr2, pgb_event_base, SIGUSR2, handle_sigusr2, NULL);
529 err = evsignal_add(&ev_sigusr2, NULL);
530 if (err < 0)
531 fatal_perror("evsignal_add");
532
533 evsignal_assign(&ev_sighup, pgb_event_base, SIGHUP, handle_sighup, NULL);
534 err = evsignal_add(&ev_sighup, NULL);
535 if (err < 0)
536 fatal_perror("evsignal_add");
537 #endif
538 evsignal_assign(&ev_sigterm, pgb_event_base, SIGTERM, handle_sigterm, NULL);
539 err = evsignal_add(&ev_sigterm, NULL);
540 if (err < 0)
541 fatal_perror("evsignal_add");
542
543 evsignal_assign(&ev_sigint, pgb_event_base, SIGINT, handle_sigint, NULL);
544 err = evsignal_add(&ev_sigint, NULL);
545 if (err < 0)
546 fatal_perror("evsignal_add");
547 }
548
549 /*
550 * daemon mode
551 */
go_daemon(void)552 static void go_daemon(void)
553 {
554 int pid, fd;
555
556 if (!cf_pidfile || !cf_pidfile[0])
557 die("daemon needs pidfile configured");
558
559 /* don't log to stdout anymore */
560 cf_quiet = 1;
561
562 /* send stdin, stdout, stderr to /dev/null */
563 fd = open("/dev/null", O_RDWR);
564 if (fd < 0)
565 die("could not open /dev/null: %s", strerror(errno));
566 dup2(fd, 0);
567 dup2(fd, 1);
568 dup2(fd, 2);
569 if (fd > 2)
570 close(fd);
571
572 /* fork new process */
573 pid = fork();
574 if (pid < 0)
575 die("fork failed: %s", strerror(errno));
576 if (pid > 0)
577 _exit(0);
578
579 /* create new session */
580 pid = setsid();
581 if (pid < 0)
582 die("setsid failed: %s", strerror(errno));
583
584 /* fork again to avoid being session leader */
585 pid = fork();
586 if (pid < 0)
587 die("fork failed: %s", strerror(errno));
588 if (pid > 0)
589 _exit(0);
590 }
591
592 /*
593 * pidfile management.
594 */
595
remove_pidfile(void)596 static void remove_pidfile(void)
597 {
598 if (cf_pidfile) {
599 if (cf_pidfile[0])
600 unlink(cf_pidfile);
601 free(cf_pidfile);
602 cf_pidfile = NULL;
603 }
604 }
605
check_pidfile(void)606 static void check_pidfile(void)
607 {
608 char buf[128 + 1];
609 pid_t pid = 0;
610 int fd, res, err;
611
612 if (!cf_pidfile || !cf_pidfile[0])
613 return;
614
615 /* read old pid */
616 fd = open(cf_pidfile, O_RDONLY);
617 if (fd < 0) {
618 if (errno == ENOENT)
619 return;
620 die("could not open pidfile '%s': %s", cf_pidfile, strerror(errno));
621 }
622 res = read(fd, buf, sizeof(buf) - 1);
623 close(fd);
624 if (res <= 0)
625 die("could not read pidfile '%s': %s", cf_pidfile, strerror(errno));
626
627 /* parse pid */
628 buf[res] = 0;
629 pid = atol(buf);
630 if (pid <= 0)
631 goto locked_pidfile;
632
633 /* check if running */
634 if (kill(pid, 0) >= 0)
635 goto locked_pidfile;
636 if (errno != ESRCH)
637 goto locked_pidfile;
638
639 /* seems the pidfile is not in use */
640 log_info("stale pidfile, removing");
641 err = unlink(cf_pidfile);
642 if (err != 0)
643 die("could not remove stale pidfile: %s", strerror(errno));
644 return;
645
646 locked_pidfile:
647 die("pidfile exists, another instance running?");
648 }
649
write_pidfile(void)650 static void write_pidfile(void)
651 {
652 char buf[64];
653 pid_t pid;
654 int res, fd;
655
656 if (!cf_pidfile || !cf_pidfile[0])
657 return;
658
659 pid = getpid();
660 snprintf(buf, sizeof(buf), "%u\n", (unsigned)pid);
661
662 fd = open(cf_pidfile, O_WRONLY | O_CREAT | O_EXCL, 0644);
663 if (fd < 0)
664 die("could not open pidfile '%s': %s", cf_pidfile, strerror(errno));
665 res = safe_write(fd, buf, strlen(buf));
666 if (res < 0)
667 die("could not write pidfile '%s': %s", cf_pidfile, strerror(errno));
668 close(fd);
669
670 /* only remove when we have it actually written */
671 atexit(remove_pidfile);
672 }
673
674 /* just print out max files, in the future may warn if something is off */
check_limits(void)675 static void check_limits(void)
676 {
677 struct rlimit lim;
678 int total_users = statlist_count(&user_list);
679 int fd_count;
680 int err;
681 struct List *item;
682 PgDatabase *db;
683
684 log_noise("event: %d, SBuf: %d, PgSocket: %d, IOBuf: %d",
685 (int)sizeof(struct event), (int)sizeof(SBuf),
686 (int)sizeof(PgSocket), (int)IOBUF_SIZE);
687
688 /* load limits */
689 err = getrlimit(RLIMIT_NOFILE, &lim);
690 if (err < 0) {
691 log_error("could not get RLIMIT_NOFILE: %s", strerror(errno));
692 return;
693 }
694
695 /* calculate theoretical max, +10 is just in case */
696 fd_count = cf_max_client_conn + 10;
697 statlist_for_each(item, &database_list) {
698 db = container_of(item, PgDatabase, head);
699 if (db->forced_user)
700 fd_count += (db->pool_size >= 0 ? db->pool_size : cf_default_pool_size);
701 else
702 fd_count += (db->pool_size >= 0 ? db->pool_size : cf_default_pool_size) * total_users;
703 }
704
705 log_info("kernel file descriptor limit: %d (hard: %d); max_client_conn: %d, max expected fd use: %d",
706 (int)lim.rlim_cur, (int)lim.rlim_max, cf_max_client_conn, fd_count);
707 }
708
check_old_process_unix(void)709 static bool check_old_process_unix(void)
710 {
711 struct sockaddr_un sa_un;
712 socklen_t len = sizeof(sa_un);
713 int domain = AF_UNIX;
714 int res, fd;
715
716 if (!cf_unix_socket_dir || !*cf_unix_socket_dir || sd_listen_fds(0) > 0)
717 return false;
718
719 memset(&sa_un, 0, len);
720 sa_un.sun_family = domain;
721 snprintf(sa_un.sun_path, sizeof(sa_un.sun_path),
722 "%s/.s.PGSQL.%d", cf_unix_socket_dir, cf_listen_port);
723
724 fd = socket(domain, SOCK_STREAM, 0);
725 if (fd < 0)
726 die("could not create socket: %s", strerror(errno));
727 res = safe_connect(fd, (struct sockaddr *)&sa_un, len);
728 safe_close(fd);
729 if (res < 0)
730 return false;
731 return true;
732 }
733
main_loop_once(void)734 static void main_loop_once(void)
735 {
736 int err;
737
738 reset_time_cache();
739
740 err = event_base_loop(pgb_event_base, EVLOOP_ONCE);
741 if (err < 0) {
742 if (errno != EINTR)
743 log_warning("event_loop failed: %s", strerror(errno));
744 }
745 pam_poll();
746 per_loop_maint();
747 reuse_just_freed_objects();
748 rescue_timers();
749 per_loop_pooler_maint();
750
751 if (adns)
752 adns_per_loop(adns);
753 }
754
takeover_part1(void)755 static void takeover_part1(void)
756 {
757 /* use temporary libevent base */
758 struct event_base *evtmp;
759
760 evtmp = pgb_event_base;
761 pgb_event_base = event_base_new();
762
763 if (!cf_unix_socket_dir || !*cf_unix_socket_dir)
764 die("cannot reboot if unix dir not configured");
765
766 /*
767 * Takeover with abstract Unix socket doesn't work because the
768 * new process can't unlink the socket used by the old process
769 * and put its own in place (see create_unix_socket()).
770 */
771 if (cf_unix_socket_dir[0] == '@')
772 die("cannot reboot with abstract Unix socket");
773
774 if (sd_listen_fds(0) > 0)
775 die("cannot reboot under service manager");
776
777 takeover_init();
778 while (cf_reboot)
779 main_loop_once();
780
781 event_base_free(pgb_event_base);
782 pgb_event_base = evtmp;
783 }
784
dns_setup(void)785 static void dns_setup(void)
786 {
787 if (adns)
788 return;
789 adns = adns_create_context();
790 if (!adns)
791 die("dns setup failed");
792 }
793
xfree(char ** ptr_p)794 static void xfree(char **ptr_p)
795 {
796 if (*ptr_p) {
797 free(*ptr_p);
798 *ptr_p = NULL;
799 }
800 }
801
802 _UNUSED
cleanup(void)803 static void cleanup(void)
804 {
805 adns_free_context(adns);
806 adns = NULL;
807
808 admin_cleanup();
809 objects_cleanup();
810 sbuf_cleanup();
811
812 event_base_free(pgb_event_base);
813
814 tls_deinit();
815 varcache_deinit();
816 pktbuf_cleanup();
817
818 reset_logging();
819
820 xfree(&cf_username);
821 xfree(&cf_config_file);
822 xfree(&cf_listen_addr);
823 xfree(&cf_unix_socket_dir);
824 xfree(&cf_unix_socket_group);
825 xfree(&cf_auth_file);
826 xfree(&cf_auth_hba_file);
827 xfree(&cf_auth_query);
828 xfree(&cf_auth_user);
829 xfree(&cf_server_reset_query);
830 xfree(&cf_server_check_query);
831 xfree(&cf_ignore_startup_params);
832 xfree(&cf_autodb_connstr);
833 xfree(&cf_jobname);
834 xfree(&cf_admin_users);
835 xfree(&cf_stats_users);
836 xfree(&cf_client_tls_protocols);
837 xfree(&cf_client_tls_ca_file);
838 xfree(&cf_client_tls_cert_file);
839 xfree(&cf_client_tls_key_file);
840 xfree(&cf_client_tls_ciphers);
841 xfree(&cf_client_tls_dheparams);
842 xfree(&cf_client_tls_ecdhecurve);
843 xfree(&cf_server_tls_protocols);
844 xfree(&cf_server_tls_ca_file);
845 xfree(&cf_server_tls_cert_file);
846 xfree(&cf_server_tls_key_file);
847 xfree(&cf_server_tls_ciphers);
848
849 xfree((char **)&cf_logfile);
850 xfree((char **)&cf_syslog_ident);
851 xfree((char **)&cf_syslog_facility);
852 }
853
854 /* boot everything */
main(int argc,char * argv[])855 int main(int argc, char *argv[])
856 {
857 int c;
858 bool did_takeover = false;
859 char *arg_username = NULL;
860 int long_idx;
861
862 static const struct option long_options[] = {
863 {"quiet", no_argument, NULL, 'q'},
864 {"verbose", no_argument, NULL, 'v'},
865 {"help", no_argument, NULL, 'h'},
866 {"daemon", no_argument, NULL, 'd'},
867 {"version", no_argument, NULL, 'V'},
868 {"reboot", no_argument, NULL, 'R'},
869 {"user", required_argument, NULL, 'u'},
870 {NULL, 0, NULL, 0}
871 };
872
873 setprogname(basename(argv[0]));
874
875 /* parse cmdline */
876 while ((c = getopt_long(argc, argv, "qvhdVRu:", long_options, &long_idx)) != -1) {
877 switch (c) {
878 case 'R':
879 cf_reboot = 1;
880 break;
881 case 'v':
882 cf_verbose++;
883 break;
884 case 'V':
885 printf("%s\n", PACKAGE_STRING);
886 printf("libevent %s\nadns: %s\ntls: %s\n",
887 event_get_version(),
888 adns_get_backend(),
889 tls_backend_version());
890 #ifdef USE_SYSTEMD
891 printf("systemd: yes\n");
892 #endif
893 return 0;
894 case 'd':
895 cf_daemon = 1;
896 break;
897 case 'q':
898 cf_quiet = 1;
899 break;
900 case 'u':
901 arg_username = optarg;
902 break;
903 case 'h':
904 usage(argv[0]);
905 break;
906 default:
907 fprintf(stderr, "Try \"%s --help\" for more information.\n", argv[0]);
908 exit(1);
909 break;
910 }
911 }
912 if (optind + 1 != argc) {
913 fprintf(stderr, "%s: no configuration file specified\n", argv[0]);
914 fprintf(stderr, "Try \"%s --help\" for more information.\n", argv[0]);
915 exit(1);
916 }
917 cf_config_file = xstrdup(argv[optind]);
918
919 init_objects();
920 load_config();
921 main_config.loaded = true;
922 init_caches();
923 logging_prefix_cb = log_socket_prefix;
924
925 if (!sbuf_tls_setup())
926 die("TLS setup failed");
927
928 /* prefer cmdline over config for username */
929 if (arg_username) {
930 if (cf_username)
931 free(cf_username);
932 cf_username = xstrdup(arg_username);
933 }
934
935 /* switch user is needed */
936 if (cf_username && *cf_username)
937 change_user(cf_username);
938
939 /* disallow running as root */
940 if (getuid() == 0)
941 die("PgBouncer should not run as root");
942
943 admin_setup();
944
945 if (cf_reboot) {
946 if (check_old_process_unix()) {
947 takeover_part1();
948 did_takeover = true;
949 } else {
950 log_info("old process not found, try to continue normally");
951 cf_reboot = 0;
952 check_pidfile();
953 }
954 } else {
955 if (check_old_process_unix())
956 die("unix socket is in use, cannot continue");
957 check_pidfile();
958 }
959
960 if (cf_daemon)
961 go_daemon();
962
963 #ifndef USE_SYSTEMD
964 if (getenv("NOTIFY_SOCKET"))
965 log_warning("apparently running under systemd with notify socket, but systemd support was not built");
966 #endif
967
968 /* need to do that after loading config; also do after
969 * go_daemon() so that output goes to log file */
970 check_limits();
971
972 /* initialize subsystems, order important */
973 srandom(time(NULL) ^ getpid());
974 if (!(pgb_event_base = event_base_new()))
975 die("event_base_new() failed");
976 dns_setup();
977 signal_setup();
978 janitor_setup();
979 stats_setup();
980
981 pam_init();
982
983 if (did_takeover) {
984 takeover_finish();
985 } else {
986 pooler_setup();
987 }
988
989 write_pidfile();
990
991 log_info("process up: %s, libevent %s (%s), adns: %s, tls: %s", PACKAGE_STRING,
992 event_get_version(), event_base_get_method(pgb_event_base), adns_get_backend(),
993 tls_backend_version());
994
995 sd_notify(0, "READY=1");
996
997 /* main loop */
998 while (cf_shutdown < 2)
999 main_loop_once();
1000
1001 /* not useful for production loads */
1002 #ifdef CASSERT
1003 cleanup();
1004 #endif
1005
1006 return 0;
1007 }
1008