summaryrefslogtreecommitdiff
path: root/sql/mysqld.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/mysqld.cc')
-rw-r--r--sql/mysqld.cc304
1 files changed, 139 insertions, 165 deletions
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 02f69e1d512..39c764d71b9 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -338,7 +338,6 @@ static char *character_set_filesystem_name;
static char *lc_messages;
static char *lc_time_names_name;
char *my_bind_addr_str;
-int server_socket_ai_family;
static char *default_collation_name;
char *default_storage_engine, *default_tmp_storage_engine;
char *enforced_storage_engine=NULL;
@@ -1349,7 +1348,8 @@ static Buffered_logs buffered_logs;
struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD()
#ifndef EMBEDDED_LIBRARY
-MYSQL_SOCKET unix_sock, base_ip_sock, extra_ip_sock;
+std::vector<MYSQL_SOCKET> listen_sockets;
+bool unix_sock_is_online= false;
/**
Error reporter that buffer log messages.
@param level log message level
@@ -1690,28 +1690,15 @@ static void close_connections(void)
/* Abort listening to new connections */
DBUG_PRINT("quit",("Closing sockets"));
- if (!opt_disable_networking )
+ for (std::vector<MYSQL_SOCKET>::iterator sock = listen_sockets.begin();
+ sock != listen_sockets.end(); ++sock)
{
- if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET)
- {
- (void) mysql_socket_close(base_ip_sock);
- base_ip_sock= MYSQL_INVALID_SOCKET;
- }
- if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET)
- {
- (void) mysql_socket_close(extra_ip_sock);
- extra_ip_sock= MYSQL_INVALID_SOCKET;
- }
+ (void) mysql_socket_close(*sock);
+ if (sock->is_unix_domain_socket)
+ (void) unlink(mysqld_unix_port);
}
+ listen_sockets.clear();
-#ifdef HAVE_SYS_UN_H
- if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
- {
- (void) mysql_socket_close(unix_sock);
- (void) unlink(mysqld_unix_port);
- unix_sock= MYSQL_INVALID_SOCKET;
- }
-#endif
end_thr_alarm(0); // Abort old alarms.
/*
@@ -1800,13 +1787,20 @@ static void close_server_sock()
#ifdef HAVE_CLOSE_SERVER_SOCK
DBUG_ENTER("close_server_sock");
- close_socket(base_ip_sock, "TCP/IP");
- close_socket(extra_ip_sock, "TCP/IP");
- close_socket(unix_sock, "unix/IP");
-
- if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
- (void) unlink(mysqld_unix_port);
- base_ip_sock= extra_ip_sock= unix_sock= MYSQL_INVALID_SOCKET;
+ for (std::vector<MYSQL_SOCKET>::iterator sock= listen_sockets.begin();
+ sock != listen_sockets.end(); ++sock)
+ {
+ if (sock->is_unix_domain_socket)
+ {
+ close_socket(*sock, "unix/IP");
+ (void) unlink(mysqld_unix_port);
+ }
+ else
+ {
+ close_socket(*sock, "TCP/IP");
+ }
+ }
+ listen_sockets.clear();
DBUG_VOID_RETURN;
#endif
@@ -2241,7 +2235,9 @@ static void set_root(const char *path)
Activate usage of a tcp port
*/
-static MYSQL_SOCKET activate_tcp_port(uint port)
+static void activate_tcp_port(uint port,
+ std::vector<MYSQL_SOCKET> *listen_sockets,
+ bool is_extra_port= false)
{
struct addrinfo *ai, *a;
struct addrinfo hints;
@@ -2273,20 +2269,6 @@ static MYSQL_SOCKET activate_tcp_port(uint port)
unireg_abort(1); /* purecov: tested */
}
- /*
- special case: for wildcard addresses prefer ipv6 over ipv4,
- because we later switch off IPV6_V6ONLY, so ipv6 wildcard
- addresses will work for ipv4 too
- */
- if (!real_bind_addr_str && ai->ai_family == AF_INET && ai->ai_next
- && ai->ai_next->ai_family == AF_INET6)
- {
- a= ai;
- ai= ai->ai_next;
- a->ai_next= ai->ai_next;
- ai->ai_next= a;
- }
-
for (a= ai; a != NULL; a= a->ai_next)
{
ip_sock= mysql_socket_socket(key_socket_tcpip, a->ai_family,
@@ -2309,99 +2291,98 @@ static MYSQL_SOCKET activate_tcp_port(uint port)
}
else
{
- server_socket_ai_family= a->ai_family;
+ ip_sock.address_family= a->ai_family;
sql_print_information("Server socket created on IP: '%s'.",
(const char *) ip_addr);
- break;
- }
- }
- if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
- {
- DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
- sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */
- unireg_abort(1); /* purecov: tested */
- }
+ if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
+ {
+ DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
+ sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */
+ unireg_abort(1); /* purecov: tested */
+ }
- mysql_socket_set_thread_owner(ip_sock);
+ mysql_socket_set_thread_owner(ip_sock);
#ifndef __WIN__
- /*
- We should not use SO_REUSEADDR on windows as this would enable a
- user to open two mysqld servers with the same TCP/IP port.
- */
- arg= 1;
- (void) mysql_socket_setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
- sizeof(arg));
+ /*
+ We should not use SO_REUSEADDR on windows as this would enable a
+ user to open two mysqld servers with the same TCP/IP port.
+ */
+ arg= 1;
+ (void) mysql_socket_setsockopt(ip_sock, SOL_SOCKET, SO_REUSEADDR,
+ (char*)&arg, sizeof(arg));
#endif /* __WIN__ */
#ifdef IPV6_V6ONLY
- /*
- For interoperability with older clients, IPv6 socket should
- listen on both IPv6 and IPv4 wildcard addresses.
- Turn off IPV6_V6ONLY option.
-
- NOTE: this will work starting from Windows Vista only.
- On Windows XP dual stack is not available, so it will not
- listen on the corresponding IPv4-address.
- */
- if (a->ai_family == AF_INET6)
- {
- arg= 0;
- (void) mysql_socket_setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY,
- (char*)&arg, sizeof(arg));
- }
+ /*
+ If an address name resolves to both IPv4 and IPv6 addresses, the server
+ will listen on them both. With IPV6_V6ONLY unset, listening on an IPv6
+ wildcard address may cause listening on an IPv4 wildcard address
+ to fail. That's why IPV6_V6ONLY needs to be forcefully turned on.
+ */
+ if (a->ai_family == AF_INET6)
+ {
+ arg= 1;
+ (void) mysql_socket_setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char*)&arg, sizeof(arg));
+ }
#endif
#ifdef IP_FREEBIND
- arg= 1;
- (void) mysql_socket_setsockopt(ip_sock, IPPROTO_IP, IP_FREEBIND, (char*) &arg,
- sizeof(arg));
+ arg= 1;
+ (void) mysql_socket_setsockopt(ip_sock, IPPROTO_IP, IP_FREEBIND,
+ (char*) &arg, sizeof(arg));
#endif
- /*
- Sometimes the port is not released fast enough when stopping and
- restarting the server. This happens quite often with the test suite
- on busy Linux systems. Retry to bind the address at these intervals:
- Sleep intervals: 1, 2, 4, 6, 9, 13, 17, 22, ...
- Retry at second: 1, 3, 7, 13, 22, 35, 52, 74, ...
- Limit the sequence by mysqld_port_timeout (set --port-open-timeout=#).
- */
- int ret;
- uint waited, retry, this_wait;
- for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
- {
- if (((ret= mysql_socket_bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) ||
- (socket_errno != SOCKET_EADDRINUSE) ||
- (waited >= mysqld_port_timeout))
- break;
- sql_print_information("Retrying bind on TCP/IP port %u", port);
- this_wait= retry * retry / 3 + 1;
- sleep(this_wait);
- }
- freeaddrinfo(ai);
- if (ret < 0)
- {
- char buff[100];
- sprintf(buff, "Can't start server: Bind on TCP/IP port. Got error: %d",
- (int) socket_errno);
- sql_perror(buff);
- sql_print_error("Do you already have another mysqld server running on "
- "port: %u ?", port);
- unireg_abort(1);
- }
- if (mysql_socket_listen(ip_sock,(int) back_log) < 0)
- {
- sql_perror("Can't start server: listen() on TCP/IP port");
- sql_print_error("listen() on TCP/IP failed with error %d",
- socket_errno);
- unireg_abort(1);
- }
+ /*
+ Sometimes the port is not released fast enough when stopping and
+ restarting the server. This happens quite often with the test suite
+ on busy Linux systems. Retry to bind the address at these intervals:
+ Sleep intervals: 1, 2, 4, 6, 9, 13, 17, 22, ...
+ Retry at second: 1, 3, 7, 13, 22, 35, 52, 74, ...
+ Limit the sequence by mysqld_port_timeout (set --port-open-timeout=#).
+ */
+ int ret;
+ uint waited, retry, this_wait;
+ for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
+ {
+ if (((ret= mysql_socket_bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 )
+ || (socket_errno != SOCKET_EADDRINUSE)
+ || (waited >= mysqld_port_timeout))
+ break;
+ sql_print_information("Retrying bind on TCP/IP port %u", port);
+ this_wait= retry * retry / 3 + 1;
+ sleep(this_wait);
+ }
+
+ if (ret < 0)
+ {
+ char buff[100];
+ sprintf(buff, "Can't start server: Bind on TCP/IP port. Got error: %d",
+ (int) socket_errno);
+ sql_perror(buff);
+ sql_print_error("Do you already have another mysqld server running on "
+ "port: %u ?", port);
+ unireg_abort(1);
+ }
+ if (mysql_socket_listen(ip_sock,(int) back_log) < 0)
+ {
+ sql_perror("Can't start server: listen() on TCP/IP port");
+ sql_print_error("listen() on TCP/IP failed with error %d",
+ socket_errno);
+ unireg_abort(1);
+ }
#ifdef FD_CLOEXEC
- (void) fcntl(mysql_socket_getfd(ip_sock), F_SETFD, FD_CLOEXEC);
+ (void) fcntl(mysql_socket_getfd(ip_sock), F_SETFD, FD_CLOEXEC);
#endif
+ ip_sock.is_extra_port= is_extra_port;
+ listen_sockets->push_back(ip_sock);
+ }
+ }
- DBUG_RETURN(ip_sock);
+ freeaddrinfo(ai);
+ DBUG_VOID_RETURN;
}
static void network_init(void)
@@ -2431,9 +2412,11 @@ static void network_init(void)
if (!opt_disable_networking && !opt_bootstrap)
{
if (mysqld_port)
- base_ip_sock= activate_tcp_port(mysqld_port);
+ activate_tcp_port(mysqld_port, &listen_sockets,
+ /* is_extra_port= */ false);
if (mysqld_extra_port)
- extra_ip_sock= activate_tcp_port(mysqld_extra_port);
+ activate_tcp_port(mysqld_extra_port, &listen_sockets,
+ /* is_extra_port= */ true);
}
#if defined(HAVE_SYS_UN_H)
@@ -2442,6 +2425,7 @@ static void network_init(void)
*/
if (mysqld_unix_port[0] && !opt_bootstrap)
{
+ MYSQL_SOCKET unix_sock= MYSQL_INVALID_SOCKET;
size_t port_len;
DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
@@ -2458,6 +2442,9 @@ static void network_init(void)
unireg_abort(1); /* purecov: inspected */
}
+ unix_sock.is_unix_domain_socket= true;
+ listen_sockets.push_back(unix_sock);
+ unix_sock_is_online= true;
mysql_socket_set_thread_owner(unix_sock);
bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
@@ -5645,8 +5632,7 @@ int mysqld_main(int argc, char **argv)
if (IS_SYSVAR_AUTOSIZE(&server_version_ptr))
sql_print_information(ER_DEFAULT(ER_STARTUP), my_progname, server_version,
- ((mysql_socket_getfd(unix_sock) == INVALID_SOCKET) ?
- (char*) "" : mysqld_unix_port),
+ (unix_sock_is_online ? mysqld_unix_port : (char*) ""),
mysqld_port, MYSQL_COMPILATION_COMMENT);
else
{
@@ -5658,8 +5644,7 @@ int mysqld_main(int argc, char **argv)
sql_print_information(ER_DEFAULT(ER_STARTUP), my_progname,
real_server_version,
- ((mysql_socket_getfd(unix_sock) == INVALID_SOCKET) ?
- (char*) "" : mysqld_unix_port),
+ (unix_sock_is_online ? mysqld_unix_port : (char*) ""),
mysqld_port, MYSQL_COMPILATION_COMMENT);
}
@@ -5866,8 +5851,7 @@ void handle_accepted_socket(MYSQL_SOCKET new_sock, MYSQL_SOCKET sock)
{
#ifdef HAVE_LIBWRAP
{
- if (mysql_socket_getfd(sock) == mysql_socket_getfd(base_ip_sock) ||
- mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock))
+ if (!sock.is_unix_domain_socket)
{
struct request_info req;
signal(SIGCHLD, SIG_DFL);
@@ -5910,11 +5894,9 @@ void handle_accepted_socket(MYSQL_SOCKET new_sock, MYSQL_SOCKET sock)
DBUG_PRINT("info", ("Creating CONNECT for new connection"));
if (auto connect= new CONNECT(new_sock,
- mysql_socket_getfd(sock) ==
- mysql_socket_getfd(unix_sock) ?
+ sock.is_unix_domain_socket ?
VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
- mysql_socket_getfd(sock) ==
- mysql_socket_getfd(extra_ip_sock) ?
+ sock.is_extra_port ?
extra_thread_scheduler : thread_scheduler))
create_new_thread(connect);
else
@@ -5950,36 +5932,30 @@ void handle_connections_sockets()
struct sockaddr_storage cAddr;
int retval;
#ifdef HAVE_POLL
- int socket_count= 0;
- struct pollfd fds[3]; // for ip_sock, unix_sock and extra_ip_sock
- MYSQL_SOCKET pfs_fds[3]; // for performance schema
-#define setup_fds(X) \
- mysql_socket_set_thread_owner(X); \
- pfs_fds[socket_count]= (X); \
- fds[socket_count].fd= mysql_socket_getfd(X); \
- fds[socket_count].events= POLLIN; \
- socket_count++
+ std::vector<struct pollfd> fds; // for ip_sock, unix_sock and extra_ip_sock
#else
-#define setup_fds(X) FD_SET(mysql_socket_getfd(X),&clientFDs)
fd_set readFDs,clientFDs;
- FD_ZERO(&clientFDs);
#endif
DBUG_ENTER("handle_connections_sockets");
- if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET)
+#ifdef HAVE_POLL
+ fds.resize(listen_sockets.size());
+ for (size_t i= 0; i < listen_sockets.size(); i++)
{
- setup_fds(base_ip_sock);
- set_non_blocking_if_supported(base_ip_sock);
+ mysql_socket_set_thread_owner(listen_sockets[i]);
+ fds[i].fd= mysql_socket_getfd(listen_sockets[i]);
+ fds[i].events= POLLIN;
+ set_non_blocking_if_supported(listen_sockets[i]);
}
- if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET)
+#else
+ FD_ZERO(&clientFDs);
+ for (size_t i= 0; i < listen_sockets.size(); i++)
{
- setup_fds(extra_ip_sock);
- set_non_blocking_if_supported(extra_ip_sock);
+ int fd= mysql_socket_getfd(listen_sockets[i]);
+ FD_SET(fd, &clientFDs);
+ set_non_blocking_if_supported(listen_sockets[i]);
}
-#ifdef HAVE_SYS_UN_H
- setup_fds(unix_sock);
- set_non_blocking_if_supported(unix_sock);
#endif
sd_notify(0, "READY=1\n"
@@ -5989,10 +5965,10 @@ void handle_connections_sockets()
while (!abort_loop)
{
#ifdef HAVE_POLL
- retval= poll(fds, socket_count, -1);
+ retval= poll(fds.data(), fds.size(), -1);
#else
readFDs=clientFDs;
- retval= select((int) 0,&readFDs,0,0,0);
+ retval= select(FD_SETSIZE, &readFDs, NULL, NULL, NULL);
#endif
if (retval < 0)
@@ -6016,22 +5992,23 @@ void handle_connections_sockets()
/* Is this a new connection request ? */
#ifdef HAVE_POLL
- for (int i= 0; i < socket_count; ++i)
+ for (size_t i= 0; i < fds.size(); ++i)
{
if (fds[i].revents & POLLIN)
{
- sock= pfs_fds[i];
+ sock= listen_sockets[i];
break;
}
}
#else // HAVE_POLL
- if (FD_ISSET(mysql_socket_getfd(base_ip_sock),&readFDs))
- sock= base_ip_sock;
- else
- if (FD_ISSET(mysql_socket_getfd(extra_ip_sock),&readFDs))
- sock= extra_ip_sock;
- else
- sock = unix_sock;
+ for (size_t i=0; i < listen_sockets.size(); i++)
+ {
+ if (FD_ISSET(mysql_socket_getfd(listen_sockets[i]), &readFDs))
+ {
+ sock= listen_sockets[i];
+ break;
+ }
+ }
#endif // HAVE_POLL
for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
@@ -7514,9 +7491,6 @@ static int mysql_init_variables(void)
character_set_filesystem= &my_charset_bin;
opt_specialflag= SPECIAL_ENGLISH;
-#ifndef EMBEDDED_LIBRARY
- unix_sock= base_ip_sock= extra_ip_sock= MYSQL_INVALID_SOCKET;
-#endif
mysql_home_ptr= mysql_home;
log_error_file_ptr= log_error_file;
protocol_version= PROTOCOL_VERSION;