pgpool2.git / summary / log / commit / refs

commit    067765e9e9fffcad21ebc0ef0e24e05f6f161b33
Author:   Tatsuo Ishii <ishii@postgresql.org>
Date:     Sat May 10 00:54:41 2014 +0000

    Fix unportable code related to SO_REUSEPORT.
    
    There are several places using setsockopt(sock, SOL_SOCKET,
    SO_REUSEPORT...). SO_REUSEPORT is not available on all Linux kernels
    and the source code uses ifdef to detect the feature in the compile
    time. Problem is, the binary created with kernel which provides the
    feature cannot run on a kernel which does not provide the feature. Fix
    is, detecting the feature in the run time by checking error code
    returned by setsockopt() and ignore it if the cause of the error is
    lacking the feature.


src/watchdog/wd_heartbeat.c | 65 ++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/src/watchdog/wd_heartbeat.c b/src/watchdog/wd_heartbeat.c index fe4280e35..875e58a2d 100644 --- a/src/watchdog/wd_heartbeat.c +++ b/src/watchdog/wd_heartbeat.c @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2013 PgPool Global Development Group + * Copyright (c) 2003-2014 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -57,6 +57,7 @@ static RETSIGTYPE hb_receiver_exit(int sig); static int hton_wd_hb_packet(WdHbPacket *to, WdHbPacket *from); static int ntoh_wd_hb_packet(WdHbPacket *to, WdHbPacket *from); static int packet_to_string_hb(WdHbPacket *pkt, char * str, int maxlen); +static int wd_set_reuseport(int sock); /* create socket for sending heartbeat */ int @@ -110,19 +111,12 @@ wd_create_hb_send_socket(WdHbIf *hb_if) #endif } -#if defined(SO_REUSEPORT) + if (wd_set_reuseport(sock) != 0) { - int one = 1; - if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) == -1) - { - pool_error("wd_create_hb_send_socket: setsockopt(SO_REUSEPORT) failed. reason: %s", - strerror(errno)); - close(sock); - return -1; - } - pool_log("wd_create_hb_send_socket: set SO_REUSEPORT"); + pool_error("wd_create_hb_send_socket: wd_set_reuseport failed"); + return -1; } -#endif + pool_log("wd_create_hb_send_socket: set SO_REUSEPORT"); if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) { pool_error("wd_create_hb_send_socket: setting close-on-exec flag failed. reason: %s", @@ -192,18 +186,12 @@ wd_create_hb_recv_socket(WdHbIf *hb_if) #endif } -#if defined(SO_REUSEPORT) + if (wd_set_reuseport(sock) != 0) { - if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) == -1) - { - pool_error("wd_create_hb_recv_socket: setsockopt(SO_REUSEPORT) failed. reason: %s", - strerror(errno)); - close(sock); - return -1; - } - pool_log("wd_create_hb_recv_socket: set SO_REUSEPORT"); + pool_error("wd_create_hb_recv_socket: wd_set_reuseport failed"); + return -1; } -#endif + pool_log("wd_create_hb_recv_socket: set SO_REUSEPORT"); bind_is_done = 0; for (bind_tries = 0; !bind_is_done && bind_tries < MAX_BIND_TRIES; bind_tries++) @@ -579,3 +567,36 @@ packet_to_string_hb(WdHbPacket *pkt, char *str, int maxlen) return len; } + +/* + * Set SO_REUSEPORT option to the socket. If the option is available + * in the compile time but not available in the run time, just emit a + * log and treat it as normal. + */ +static int wd_set_reuseport(int sock) +{ +#if defined(SO_REUSEPORT) + int one = 1; + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) == -1) + { + if (errno == EINVAL || errno == ENOPROTOOPT) + { + pool_log("wd_create_hb_send_socket: setsockopt(SO_REUSEPORT) is not supported by the kernel. detail: %s", + strerror(errno)); + } + else + { + pool_error("wd_create_hb_send_socket: setsockopt(SO_REUSEPORT) failed. reason: %s", + strerror(errno)); + close(sock); + return -1; + } + } + else + pool_log("wd_create_hb_send_socket: set SO_REUSEPORT"); + return 0; +#else + return 0; +#endif +} [parent: efa74af06f1c]