From: Marko Kreen Date: Wed, 29 Sep 2010 16:41:20 +0000 (-0700) Subject: Avoid fatal() in tune_socket() X-Git-Tag: pgbouncer_1_4_rc3~30 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=010185e3ea3cefed083672e7596abfac346d5d45;p=pgbouncer Avoid fatal() in tune_socket() This allows to survive broken fds send during reboot from old pooler. --- diff --git a/include/util.h b/include/util.h index 5322800..ad5bafa 100644 --- a/include/util.h +++ b/include/util.h @@ -42,7 +42,7 @@ int log_socket_prefix(enum LogLevel lev, void *ctx, char *dst, unsigned int dstl void pg_md5_encrypt(const char *part1, const char *part2, size_t p2len, char *dest); void get_random_bytes(uint8_t *dest, int len); -void tune_socket(int sock, bool is_unix); +bool tune_socket(int sock, bool is_unix) _MUSTCHECK; bool strlist_contains(const char *liststr, const char *str); diff --git a/src/pooler.c b/src/pooler.c index 8b7fd4c..008242b 100644 --- a/src/pooler.c +++ b/src/pooler.c @@ -95,7 +95,8 @@ static int create_unix_socket(const char *socket_dir, int listen_port) atexit(cleanup_unix_socket); /* set common options */ - tune_socket(sock, true); + if (!tune_socket(sock, true)) + fatal_perror("tune_socket"); /* finally, accept connections */ res = listen(sock, cf_listen_backlog); @@ -191,7 +192,8 @@ static int create_net_socket(const char *listen_addr, int listen_port) fatal_perror("bind"); /* set common options */ - tune_socket(sock, false); + if (!tune_socket(sock, false)) + fatal_perror("tune_socket"); /* make it accept connections */ res = listen(sock, cf_listen_backlog); @@ -301,7 +303,8 @@ loop: bool use_pooler_socket(int sock, bool is_unix) { - tune_socket(sock, is_unix); + if (!tune_socket(sock, is_unix)) + return false; if (is_unix) fd_unix = sock; diff --git a/src/sbuf.c b/src/sbuf.c index 6f95023..d6e4744 100644 --- a/src/sbuf.c +++ b/src/sbuf.c @@ -86,15 +86,14 @@ bool sbuf_accept(SBuf *sbuf, int sock, bool is_unix) Assert(iobuf_empty(sbuf->io) && sbuf->sock == 0); AssertSanity(sbuf); - tune_socket(sock, is_unix); sbuf->sock = sock; + if (!tune_socket(sock, is_unix)) + goto failed; if (!cf_reboot) { res = sbuf_wait_for_data(sbuf); - if (!res) { - sbuf_call_proto(sbuf, SBUF_EV_RECV_FAILED); - return false; - } + if (!res) + goto failed; /* socket should already have some data (linux only) */ if (cf_tcp_defer_accept && !is_unix) { sbuf_main_loop(sbuf, DO_RECV); @@ -103,6 +102,9 @@ bool sbuf_accept(SBuf *sbuf, int sock, bool is_unix) } } return true; +failed: + sbuf_call_proto(sbuf, SBUF_EV_RECV_FAILED); + return false; } /* need to connect() to get a socket */ @@ -123,7 +125,8 @@ bool sbuf_connect(SBuf *sbuf, const struct sockaddr *sa, int sa_len, int timeout /* probably fd limit */ goto failed; - tune_socket(sock, is_unix); + if (!tune_socket(sock, is_unix)) + goto failed; sbuf->sock = sock; diff --git a/src/util.c b/src/util.c index f330c9f..3f8a624 100644 --- a/src/util.c +++ b/src/util.c @@ -90,7 +90,7 @@ void get_random_bytes(uint8_t *dest, int len) } /* set needed socket options */ -void tune_socket(int sock, bool is_unix) +bool tune_socket(int sock, bool is_unix) { int res; int val; @@ -98,7 +98,7 @@ void tune_socket(int sock, bool is_unix) /* close fd on exec */ res = fcntl(sock, F_SETFD, FD_CLOEXEC); if (res < 0) - fatal_perror("fcntl FD_CLOEXEC"); + goto fail; /* when no data available, return EAGAIN instead blocking */ socket_set_nonblocking(sock, 1); @@ -108,14 +108,14 @@ void tune_socket(int sock, bool is_unix) val = 1; res = setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val)); if (res < 0) - fatal_perror("setsockopt SO_NOSIGPIPE"); + goto fail; #endif /* * Following options are for network sockets */ if (is_unix) - return; + return true; /* the keepalive stuff needs some poking before enbling */ if (cf_tcp_keepalive) { @@ -123,28 +123,28 @@ void tune_socket(int sock, bool is_unix) val = 1; res = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)); if (res < 0) - fatal_perror("setsockopt SO_KEEPALIVE"); + goto fail; #ifdef __linux__ /* set count of keepalive packets */ if (cf_tcp_keepcnt > 0) { val = cf_tcp_keepcnt; res = setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)); if (res < 0) - fatal_perror("setsockopt TCP_KEEPCNT"); + goto fail; } /* how long the connection can stay idle before sending keepalive pkts */ if (cf_tcp_keepidle) { val = cf_tcp_keepidle; res = setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)); if (res < 0) - fatal_perror("setsockopt TCP_KEEPIDLE"); + goto fail; } /* time between packets */ if (cf_tcp_keepintvl) { val = cf_tcp_keepintvl; res = setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)); if (res < 0) - fatal_perror("setsockopt TCP_KEEPINTVL"); + goto fail; } #else #ifdef TCP_KEEPALIVE @@ -152,7 +152,7 @@ void tune_socket(int sock, bool is_unix) val = cf_tcp_keepidle; res = setsockopt(sock, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)); if (res < 0) - fatal_perror("setsockopt TCP_KEEPALIVE"); + goto fail; } #endif #endif @@ -163,11 +163,11 @@ void tune_socket(int sock, bool is_unix) val = cf_tcp_socket_buffer; res = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)); if (res < 0) - fatal_perror("setsockopt SO_SNDBUF"); + goto fail; val = cf_tcp_socket_buffer; res = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)); if (res < 0) - fatal_perror("setsockopt SO_RCVBUF"); + goto fail; } /* @@ -176,7 +176,11 @@ void tune_socket(int sock, bool is_unix) val = 1; res = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); if (res < 0) - fatal_perror("setsockopt TCP_NODELAY"); + goto fail; + return true; +fail: + log_warning("tune_socket(%d) failed: %s", sock, strerror(errno)); + return false; } /*