Skip to content

Commit 672b8d6

Browse files
committed
Bug#24303169 XPLUGIN SOCKET/TCP CONNECT ISSUES FOR CONCCURENT CONNECTIONS
Description There are two issues in the bug. First one related to limited number of file descriptors and X Plugin prints trace errors (it only occurs with UNIX sockets). Second one is about using invalid file descriptor by X Plugin. Analysis of first problem The limit of descriptors was set to 1024 which is less than system variable `max_connection` (900) and should be sufficient for the test. X Plugin accesses user table at startup (mysql.user) which also creates a descriptor. We get two descriptors per connection, thus the limit of descriptors should be set to 1800. The issue isn't reproducable with TCP sockets because the sockets are much slower and they get sufficient time not to release the mysql.user file descriptor (not are opened simultaneously). Analysis of second problem `Connecton_listener_interface` can return a Vio structure with invalid socket inside. `ngs::Server::on_accept` didn't check if `Vio` is valid. Solution Fixed second problem by validating the socket and returning NULL pointer to `Vio` object, `ngs::Server` counts such objects as accept failure. To prevent trace error overflow added additional counting of accept failures and printing the error when `num_of_accept_error %244 == 0`. RB: 13538 Reviewed-by: Grzegorz Szwarc <[email protected]>
1 parent 6bdad5c commit 672b8d6

File tree

13 files changed

+82
-59
lines changed

13 files changed

+82
-59
lines changed

rapid/plugin/x/ngs/include/ngs/interface/listener_factory_interface.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,10 @@ typedef Memory_new<Listener_interface>::Unique_ptr Listener_interface_ptr;
3333
class Listener_factory_interface
3434
{
3535
public:
36-
3736
virtual ~Listener_factory_interface() {}
3837

39-
virtual Listener_interface_ptr create_unix_socket_listener(const std::string &unix_socket_path, Time_and_socket_events &event) = 0;
40-
virtual Listener_interface_ptr create_tcp_socket_listener(const unsigned short port, Time_and_socket_events &event) = 0;
38+
virtual Listener_interface_ptr create_unix_socket_listener(const std::string &unix_socket_path, Time_and_socket_events &event, const uint32 backlog) = 0;
39+
virtual Listener_interface_ptr create_tcp_socket_listener(const unsigned short port, Time_and_socket_events &event, const uint32 backlog) = 0;
4140
};
4241

4342
} // namespace ngs

rapid/plugin/x/ngs/include/ngs/server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class Server: public Server_interface
147147

148148
bool m_timer_running;
149149
bool m_skip_name_resolve;
150+
uint32 m_errors_while_accepting;
150151

151152
boost::shared_ptr<Server_acceptors> m_acceptors;
152153
boost::shared_ptr<Scheduler_dynamic> m_accept_scheduler;

rapid/plugin/x/ngs/include/ngs/server_acceptors.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class Server_acceptors
4141

4242
Server_acceptors(Listener_factory_interface &listener_factory,
4343
const unsigned short tcp_port,
44-
const std::string &unix_socket_file_or_named_pipe);
44+
const std::string &unix_socket_file_or_named_pipe,
45+
const uint32 backlog);
4546

4647
bool prepare(On_connection on_connection, const bool skip_networking, const bool use_unix_sockets_or_named_pipes);
4748
void abort();

rapid/plugin/x/ngs/include/ngs_common/connection_vio.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ class Connection_vio
111111

112112
static my_socket accept(my_socket sock, struct sockaddr* addr, socklen_t& len, int& err, std::string& strerr);
113113

114-
static my_socket create_and_bind_socket(const unsigned short port, std::string &error_message);
115-
static my_socket create_and_bind_socket(const std::string &unix_socket_file, std::string &error_message);
114+
static my_socket create_and_bind_socket(const unsigned short port, std::string &error_message, const uint32 backlog);
115+
static my_socket create_and_bind_socket(const std::string &unix_socket_file, std::string &error_message, const uint32 backlog);
116116

117117
static void get_error(int& err, std::string& strerr);
118118

@@ -123,7 +123,6 @@ class Connection_vio
123123
private:
124124
static bool create_lockfile(const std::string &unix_socket_file, std::string &error_message);
125125
static std::string get_lockfile_name(const std::string &unix_socket_file);
126-
127126
friend class Ssl_context;
128127

129128
Mutex m_shutdown_mutex;

rapid/plugin/x/ngs/ngs_common/connection_vio.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ my_socket Connection_vio::accept(my_socket sock, struct sockaddr* addr, socklen_
411411
return res;
412412
}
413413

414-
my_socket Connection_vio::create_and_bind_socket(const unsigned short port, std::string &error_message)
414+
my_socket Connection_vio::create_and_bind_socket(const unsigned short port, std::string &error_message, const uint32 backlog)
415415
{
416416
int err;
417417
std::string errstr;
@@ -450,7 +450,7 @@ my_socket Connection_vio::create_and_bind_socket(const unsigned short port, std:
450450
return INVALID_SOCKET;
451451
}
452452

453-
if (m_socket_operations->listen(result, 9999) < 0)
453+
if (m_socket_operations->listen(result, backlog) < 0)
454454
{
455455
// lets decide later if its an error or not
456456
get_error(err, errstr);
@@ -467,7 +467,7 @@ my_socket Connection_vio::create_and_bind_socket(const unsigned short port, std:
467467
return result;
468468
}
469469

470-
my_socket Connection_vio::create_and_bind_socket(const std::string &unix_socket_file, std::string &error_message)
470+
my_socket Connection_vio::create_and_bind_socket(const std::string &unix_socket_file, std::string &error_message, const uint32 backlog)
471471
{
472472
#if defined(HAVE_SYS_UN_H)
473473
struct sockaddr_un addr;
@@ -535,7 +535,7 @@ my_socket Connection_vio::create_and_bind_socket(const std::string &unix_socket_
535535
umask(old_mask);
536536

537537
// listen
538-
if (m_socket_operations->listen(listener_socket, 9999) < 0)
538+
if (m_socket_operations->listen(listener_socket, backlog) < 0)
539539
{
540540
get_error(err, errstr);
541541

@@ -563,7 +563,7 @@ bool Connection_vio::create_lockfile(const std::string &unix_socket_file, std::s
563563
char buffer[8];
564564
const char x_prefix = 'X';
565565
const pid_t cur_pid= m_system_operations->getpid();
566-
std::string lock_filename= get_lockfile_name(unix_socket_file);
566+
const std::string lock_filename= get_lockfile_name(unix_socket_file);
567567

568568
compile_time_assert(sizeof(pid_t) == 4);
569569
int retries= 3;

rapid/plugin/x/ngs/src/server.cc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Server::Server(boost::shared_ptr<Server_acceptors> acceptors,
4444
boost::shared_ptr<Protocol_config> config)
4545
: m_timer_running(false),
4646
m_skip_name_resolve(false),
47+
m_errors_while_accepting(0),
4748
m_acceptors(acceptors),
4849
m_accept_scheduler(accept_scheduler),
4950
m_worker_scheduler(work_scheduler),
@@ -270,18 +271,21 @@ void Server::on_accept(Connection_acceptor_interface &connection_acceptor)
270271
if (m_state.is(State_terminating))
271272
return;
272273

273-
int err = 0;
274-
std::string strerr;
275274
Vio *vio = connection_acceptor.accept();
276275

277276
if (NULL == vio)
278277
{
279278
m_delegate->did_reject_client(Server_delegate::AcceptError);
280279

281-
// error accepting client
282-
log_error("Error accepting client: "
283-
"Error code: %s (%d)",
284-
strerr.c_str(), err);
280+
if (0 == (m_errors_while_accepting++ & 255))
281+
{
282+
// error accepting client
283+
log_error("Error accepting client");
284+
}
285+
const time_t microseconds_to_sleep = 100000;
286+
287+
my_sleep(microseconds_to_sleep);
288+
285289
return;
286290
}
287291

rapid/plugin/x/ngs/src/server_acceptors.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ class Server_acceptors::Server_task_time_and_event: public Server_task_interface
120120
Server_acceptors::Server_acceptors(
121121
Listener_factory_interface &listener_factory,
122122
const unsigned short tcp_port,
123-
const std::string &unix_socket_file_or_named_pipe)
124-
: m_tcp_socket(listener_factory.create_tcp_socket_listener(tcp_port, m_event)),
123+
const std::string &unix_socket_file_or_named_pipe, const uint32 backlog)
124+
: m_tcp_socket(listener_factory.create_tcp_socket_listener(tcp_port, m_event, backlog)),
125125
#if defined(HAVE_SYS_UN_H)
126-
m_unix_socket(listener_factory.create_unix_socket_listener(unix_socket_file_or_named_pipe, m_event)),
126+
m_unix_socket(listener_factory.create_unix_socket_listener(unix_socket_file_or_named_pipe, m_event, backlog)),
127127
#endif
128128
m_time_and_event_state(State_listener_initializing),
129129
m_time_and_event_task(new Server_task_time_and_event(m_event, m_time_and_event_state))

rapid/plugin/x/ngs/src/time_socket_events.cc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,37 @@ class Connection_acceptor_socket : public Connection_acceptor_interface
3434
{
3535
Vio *vio;
3636
sockaddr_storage accept_address;
37-
socklen_t accept_len = sizeof(accept_address);
3837
int err = 0;
3938
std::string strerr;
39+
my_socket sock = INVALID_SOCKET;
4040

41-
my_socket sock = Connection_vio::accept(m_socket_listener, (struct sockaddr*)&accept_address, accept_len, err, strerr);
42-
const bool is_tcpip = (accept_address.ss_family == AF_INET || accept_address.ss_family == AF_INET6);
41+
for (int i = 0; i < MAX_ACCEPT_REATTEMPT; ++i)
42+
{
43+
socklen_t accept_len = sizeof(accept_address);
44+
sock = Connection_vio::accept(m_socket_listener, (struct sockaddr*)&accept_address, accept_len, err, strerr);
45+
46+
if (INVALID_SOCKET != sock)
47+
break;
48+
}
4349

50+
if (INVALID_SOCKET == sock)
51+
return NULL;
52+
53+
const bool is_tcpip = (accept_address.ss_family == AF_INET || accept_address.ss_family == AF_INET6);
4454
vio = vio_new(sock, is_tcpip ? VIO_TYPE_TCPIP : VIO_TYPE_SOCKET, 0);
4555
if (!vio)
4656
throw std::bad_alloc();
57+
4758
// enable TCP_NODELAY
4859
vio_fastsend(vio);
49-
5060
vio_keepalive(vio, TRUE);
5161

5262
return vio;
5363
}
5464

5565
private:
5666
my_socket m_socket_listener;
67+
static const int MAX_ACCEPT_REATTEMPT = 10;
5768
};
5869

5970

rapid/plugin/x/src/xpl_listener_factory.cc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ namespace details
3131
class Tcp_listener: public ngs::Listener_interface
3232
{
3333
public:
34-
Tcp_listener(const unsigned short port, ngs::Time_and_socket_events &event)
34+
Tcp_listener(const unsigned short port, ngs::Time_and_socket_events &event, const uint32 backlog)
3535
: m_state(ngs::State_listener_initializing),
3636
m_port(port),
3737
m_event(event)
3838
{
39-
m_tcp_socket = ngs::Connection_vio::create_and_bind_socket(port, m_last_error);
39+
m_tcp_socket = ngs::Connection_vio::create_and_bind_socket(port, m_last_error, backlog);
4040
}
4141

4242
~Tcp_listener()
@@ -119,15 +119,16 @@ class Tcp_listener: public ngs::Listener_interface
119119
class Unix_socket_listener: public ngs::Listener_interface
120120
{
121121
public:
122-
Unix_socket_listener(const std::string &unix_socket_path, ngs::Time_and_socket_events &event)
122+
Unix_socket_listener(const std::string &unix_socket_path, ngs::Time_and_socket_events &event, const uint32 backlog)
123123
: m_state(ngs::State_listener_initializing),
124124
m_unix_socket_path(unix_socket_path),
125+
m_unix_socket(INVALID_SOCKET),
125126
m_event(event)
126127
{
127128
#if !defined(HAVE_SYS_UN_H)
128129
m_state.set(ngs::State_listener_stopped);
129130
#else
130-
m_unix_socket = ngs::Connection_vio::create_and_bind_socket(unix_socket_path, m_last_error);
131+
m_unix_socket = ngs::Connection_vio::create_and_bind_socket(unix_socket_path, m_last_error, backlog);
131132
#endif // !defined(HAVE_SYS_UN_H)
132133
}
133134

@@ -209,14 +210,14 @@ class Unix_socket_listener: public ngs::Listener_interface
209210
} // namespace details
210211

211212

212-
ngs::Listener_interface_ptr Listener_factory::create_unix_socket_listener(const std::string &unix_socket_path, ngs::Time_and_socket_events &event)
213+
ngs::Listener_interface_ptr Listener_factory::create_unix_socket_listener(const std::string &unix_socket_path, ngs::Time_and_socket_events &event, const uint32 backlog)
213214
{
214215
return ngs::Listener_interface_ptr(
215-
new details::Unix_socket_listener(unix_socket_path, event));
216+
new details::Unix_socket_listener(unix_socket_path, event, backlog));
216217
}
217218

218-
ngs::Listener_interface_ptr Listener_factory::create_tcp_socket_listener(const unsigned short port, ngs::Time_and_socket_events &event)
219+
ngs::Listener_interface_ptr Listener_factory::create_tcp_socket_listener(const unsigned short port, ngs::Time_and_socket_events &event, const uint32 backlog)
219220
{
220221
return ngs::Listener_interface_ptr(
221-
new details::Tcp_listener(port, event));
222+
new details::Tcp_listener(port, event, backlog));
222223
}

rapid/plugin/x/src/xpl_listener_factory.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ namespace xpl
2929
class Listener_factory: public ngs::Listener_factory_interface
3030
{
3131
public:
32-
ngs::Listener_interface_ptr create_unix_socket_listener(const std::string &unix_socket_path, ngs::Time_and_socket_events &event);
33-
ngs::Listener_interface_ptr create_tcp_socket_listener(const unsigned short port, ngs::Time_and_socket_events &event);
32+
ngs::Listener_interface_ptr create_unix_socket_listener(const std::string &unix_socket_path, ngs::Time_and_socket_events &event, const uint32 backlog);
33+
ngs::Listener_interface_ptr create_tcp_socket_listener(const unsigned short port, ngs::Time_and_socket_events &event, const uint32 backlog);
3434
};
3535

3636
} // namespace xpl

rapid/plugin/x/src/xpl_server.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ int xpl::Server::main(MYSQL_PLUGIN p)
271271
{
272272
xpl::plugin_handle = p;
273273

274+
uint32 listen_backlog = 50 + Plugin_system_variables::max_connections / 5;
275+
if (listen_backlog > 900)
276+
listen_backlog= 900;
277+
274278
try
275279
{
276280
Global_status_variables::instance().reset();
@@ -284,7 +288,7 @@ int xpl::Server::main(MYSQL_PLUGIN p)
284288

285289
Listener_factory listener_factory;
286290
boost::shared_ptr<ngs::Server_acceptors> acceptors(
287-
new ngs::Server_acceptors(listener_factory, Plugin_system_variables::port, Plugin_system_variables::socket));
291+
new ngs::Server_acceptors(listener_factory, Plugin_system_variables::port, Plugin_system_variables::socket, listen_backlog));
288292

289293
instance_rwl.wlock();
290294

rapid/unittest/gunit/xplugin/TestGroups.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,7 @@ add_test(InstantiationNegativeTest/Query_string_builder_multiple_too_many_tags_p
3636
add_test(Valid_ip_mask_addresses/User_verification_dbuser_param_valid_test xplugin_unit_tests --gtest_filter=Valid_ip_mask_addresses/User_verification_dbuser_param_valid_test.*)
3737
add_test(Invalid_ip_mask_addresses/User_verification_dbuser_param_notvalid_test xplugin_unit_tests --gtest_filter=Invalid_ip_mask_addresses/User_verification_dbuser_param_notvalid_test.*)
3838
add_test(Range_from_0_to_9/User_verification_param_test xplugin_unit_tests --gtest_filter=Range_from_0_to_9/User_verification_param_test.*)
39+
add_test(Supported_connection_type_require_transport_combinations/User_verification_param_test_with_supported_combinations xplugin_unit_tests --gtest_filter=Supported_connection_type_require_transport_combinations/User_verification_param_test_with_supported_combinations.*)
40+
add_test(Unsupported_connection_type_require_transport_combinations/User_verification_param_test_with_unsupported_combinations xplugin_unit_tests --gtest_filter=Unsupported_connection_type_require_transport_combinations/User_verification_param_test_with_unsupported_combinations.*)
3941
add_test(InstantiationNegativeTests/Getter_any_type_testsuite xplugin_unit_tests --gtest_filter=InstantiationNegativeTests/Getter_any_type_testsuite.*)
4042
add_test(InstantiationNegativeTests/Getter_scalar_type_testsuite xplugin_unit_tests --gtest_filter=InstantiationNegativeTests/Getter_scalar_type_testsuite.*)

0 commit comments

Comments
 (0)