Skip to content

Commit 6bdad5c

Browse files
committed
BUG#24296005 XPLUGIN UNIX SOCK NOT CLEANED AFTER SERVER CLEAN SHUTDOWN/XPLUGIN NOT INSTALLED
Description: Unix socket file and lock file were not deleted by X Plugin. Solution: In case of successful allocation of UNIX socket the plugin when exiting is going to call `unlink` on both socket and lock file. RB: 13542 Reviewed-by: Grzegorz Szwarc <grzegorz.szwarc@oracle.com>
1 parent e493545 commit 6bdad5c

File tree

7 files changed

+85
-10
lines changed

7 files changed

+85
-10
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ class Connection_vio
107107
void close();
108108

109109
static void close_socket(my_socket &fd);
110+
static void unlink_unix_socket_file(const std::string &unix_socket_file);
111+
110112
static my_socket accept(my_socket sock, struct sockaddr* addr, socklen_t& len, int& err, std::string& strerr);
111113

112114
static my_socket create_and_bind_socket(const unsigned short port, std::string &error_message);
@@ -120,6 +122,7 @@ class Connection_vio
120122

121123
private:
122124
static bool create_lockfile(const std::string &unix_socket_file, std::string &error_message);
125+
static std::string get_lockfile_name(const std::string &unix_socket_file);
123126

124127
friend class Ssl_context;
125128

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,20 @@ void Connection_vio::close_socket(my_socket &fd)
353353
}
354354
}
355355

356+
void Connection_vio::unlink_unix_socket_file(const std::string &unix_socket_file)
357+
{
358+
if (unix_socket_file.empty())
359+
return;
360+
361+
if (!m_system_operations)
362+
return;
363+
364+
const std::string unix_socket_lockfile = get_lockfile_name(unix_socket_file);
365+
366+
(void) m_system_operations->unlink(unix_socket_file.c_str());
367+
(void) m_system_operations->unlink(unix_socket_lockfile.c_str());
368+
}
369+
356370
void Connection_vio::get_error(int& err, std::string& strerr)
357371
{
358372
err = socket_errno;
@@ -549,7 +563,7 @@ bool Connection_vio::create_lockfile(const std::string &unix_socket_file, std::s
549563
char buffer[8];
550564
const char x_prefix = 'X';
551565
const pid_t cur_pid= m_system_operations->getpid();
552-
std::string lock_filename= unix_socket_file + ".lock";
566+
std::string lock_filename= get_lockfile_name(unix_socket_file);
553567

554568
compile_time_assert(sizeof(pid_t) == 4);
555569
int retries= 3;
@@ -685,6 +699,11 @@ bool Connection_vio::create_lockfile(const std::string &unix_socket_file, std::s
685699
#endif // defined(HAVE_SYS_UN_H)
686700
}
687701

702+
std::string Connection_vio::get_lockfile_name(const std::string &unix_socket_file)
703+
{
704+
return unix_socket_file+ ".lock";
705+
}
706+
688707
Socket_operations_interface::Unique_ptr Connection_vio::m_socket_operations;
689708
System_operations_interface::Unique_ptr Connection_vio::m_system_operations;
690709

rapid/plugin/x/src/xpl_listener_factory.cc

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class Tcp_listener: public ngs::Listener_interface
4141

4242
~Tcp_listener()
4343
{
44-
::ngs::Connection_vio::close_socket(m_tcp_socket);
44+
// close_listener() can be called multiple times, by user + from destructor
45+
close_listener();
4546
}
4647

4748
Sync_variable_state &get_state()
@@ -94,6 +95,11 @@ class Tcp_listener: public ngs::Listener_interface
9495

9596
void close_listener()
9697
{
98+
// Connection_vio::close_socket can be called multiple times
99+
// it invalidates the content of m_tcp_socket thus at next call
100+
// it does nothing
101+
//
102+
// Same applies to close_listener()
97103
ngs::Connection_vio::close_socket(m_tcp_socket);
98104
}
99105

@@ -127,7 +133,8 @@ class Unix_socket_listener: public ngs::Listener_interface
127133

128134
~Unix_socket_listener()
129135
{
130-
ngs::Connection_vio::close_socket(m_unix_socket);
136+
// close_listener() can be called multiple times, by user + from destructor
137+
close_listener();
131138
}
132139

133140
Sync_variable_state &get_state()
@@ -179,7 +186,11 @@ class Unix_socket_listener: public ngs::Listener_interface
179186

180187
void close_listener()
181188
{
189+
const bool should_unlink_unix_socket = INVALID_SOCKET != m_unix_socket;
182190
ngs::Connection_vio::close_socket(m_unix_socket);
191+
192+
if (should_unlink_unix_socket)
193+
ngs::Connection_vio::unlink_unix_socket_file(m_unix_socket_path);
183194
}
184195

185196
void loop()

rapid/plugin/x/tests/mtr/r/connection_unixsocket_invalid.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ ok
2424
Check if mysqlx_socket is empty
2525
result
2626
1
27-
ERROR: Connection refused, while connecting to SOCKET
27+
ERROR: No such file or directory connecting to SOCKET
2828
call mtr.add_suppression("Plugin mysqlx reported: .X Plugin failed to setup UNIX socket ./dev/null/mysqlx\.sock., with:");
2929
call mtr.add_suppression("Plugin mysqlx reported: .could not create UNIX socket lock file /dev/null/mysqlx\.sock\.lock");
3030
# restart: --loose-mysqlx-socket=/dev/null/mysqlx.sock
@@ -35,7 +35,7 @@ ok
3535
Check if mysqlx_socket is empty
3636
result
3737
1
38-
ERROR: Connection refused, while connecting to SOCKET
38+
ERROR: No such file or directory connecting to SOCKET
3939
ERROR: Not a directory, while connecting to SOCKET
4040
UNINSTALL PLUGIN mysqlx;
4141
# restart: --loose-mysqlx-socket=SOCKET

rapid/plugin/x/tests/mtr/t/connection_unixsocket.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ Mysqlx.Crud.Find {
8282

8383
EOF
8484

85+
# Server was started with UNIX socket support
86+
# Check if UNIX socket file and lock file exist
87+
--file_exists $MASTER_X_MYSOCK
88+
--file_exists $MASTER_X_MYSOCK.lock
89+
8590
--error 1
8691
--exec $MYSQLXTEST --socket=$MASTER_X_MYSOCK -uuser_127_0_0_1 --password='' --file=$MYSQL_TMP_DIR/basic_connection.tmp 2>&1
8792
--error 1
@@ -166,6 +171,15 @@ EOF
166171
let $restart_parameters = restart: --mysqlx-socket=$MYSQL_TMP_DIR/valid_mysqlx.sock;
167172
--source include/restart_mysqld.inc
168173

174+
# MySQL Server was started with new UNIX socket file for X Plugin
175+
# Check if old UNIX socket file was removed and lockfile
176+
--error 1
177+
--file_exists $MASTER_X_MYSOCK
178+
--error 1
179+
--file_exists $MASTER_X_MYSOCK.lock
180+
181+
# Check if the X Plugin is accessable through
182+
# new file
169183
--exec $MYSQLXTEST --socket=$MYSQL_TMP_DIR/valid_mysqlx.sock -uroot --password='' --file=$MYSQL_TMP_DIR/check_unixsocket.tmp 2>&1
170184

171185
## Postamble

rapid/plugin/x/tests/mtr/t/connection_unixsocket_invalid.test

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ let $restart_parameters = restart: --loose-mysqlx-socket=;
4242
--eval select (IF(VARIABLE_VALUE is NULL, "",VARIABLE_VALUE) = "") as 'result' FROM performance_schema.global_status WHERE VARIABLE_NAME like 'Mysqlx_socket';
4343
--enable_query_log
4444

45-
--replace_regex /ERROR: Connection refused, while connecting to .+\.sock/ERROR: Connection refused, while connecting to SOCKET/
45+
--replace_regex /ERROR: No such file or directory, while connecting to .+\.sock/ERROR: No such file or directory connecting to SOCKET/
4646
--error 1
4747
--exec $MYSQLXTEST --socket=$MASTER_X_MYSOCK -uroot --password='' --file=$MYSQL_TMP_DIR/check_unixsocket.tmp 2>&1
4848

@@ -59,7 +59,7 @@ let $restart_parameters = restart: --loose-mysqlx-socket="/dev/null/mysqlx.sock"
5959
--eval select (IF(VARIABLE_VALUE is NULL, "",VARIABLE_VALUE) = "") as 'result' FROM performance_schema.global_status WHERE VARIABLE_NAME like 'Mysqlx_socket';
6060
--enable_query_log
6161

62-
--replace_regex /ERROR: Connection refused, while connecting to .+\.sock/ERROR: Connection refused, while connecting to SOCKET/
62+
--replace_regex /ERROR: No such file or directory, while connecting to .+\.sock/ERROR: No such file or directory connecting to SOCKET/
6363
--error 1
6464
--exec $MYSQLXTEST --socket=$MASTER_X_MYSOCK -uroot --password='' --file=$MYSQL_TMP_DIR/check_unixsocket.tmp 2>&1
6565

@@ -192,7 +192,6 @@ let $restart_parameters = restart: --loose-mysqlx-socket=$MYSQL_TMP_DIR/long_dir
192192
--exec $MYSQLXTEST --socket=$MYSQL_TMP_DIR/long_dir012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/mysqlx.socket -uroot --password='' --file=$MYSQL_TMP_DIR/check_unixsocket.tmp 2>&1
193193

194194
## Postamble
195-
--remove_file $MYSQL_TMP_DIR/create_socket_on_this_file.tmp
196195
--remove_file $MYSQL_TMP_DIR/check_unixsocket.tmp
197196
--remove_file $MYSQL_TMP_DIR/check_connection.tmp
198197
--rmdir $MYSQL_TMP_DIR/directory

rapid/unittest/gunit/xplugin/connection_vio_t.cc

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ namespace ngs
4242
{
4343
m_connection_vio.reset(new Connection_vio(m_ssl_context, NULL));
4444

45-
m_mock_socket_operations = new Mock_socket_operations();
45+
m_mock_socket_operations = new StrictMock<Mock_socket_operations>();
4646
m_connection_vio->set_socket_operations(m_mock_socket_operations);
4747

48-
m_mock_system_operations = new Mock_system_operations();
48+
m_mock_system_operations = new StrictMock<Mock_system_operations>();
4949
m_connection_vio->set_system_operations(m_mock_system_operations);
5050
}
5151

@@ -466,5 +466,34 @@ namespace ngs
466466
ASSERT_EQ(INVALID_SOCKET, result);
467467
#endif // !defined(HAVE_SYS_UN_H)
468468
}
469+
470+
TEST_F(Connection_vio_test, try_to_unlink_empty_string)
471+
{
472+
const std::string expected_unix_socket_file = "";
473+
474+
// Does nothing
475+
Connection_vio::unlink_unix_socket_file(expected_unix_socket_file);
476+
}
477+
478+
TEST_F(Connection_vio_test, try_to_unlink_when_system_interfaces_are_not_set)
479+
{
480+
const std::string expected_unix_socket_file = "existing file";
481+
482+
m_connection_vio->set_system_operations(NULL);
483+
484+
// Does nothing
485+
Connection_vio::unlink_unix_socket_file(expected_unix_socket_file);
486+
}
487+
488+
TEST_F(Connection_vio_test, try_to_unlink_existing_unix_socket_file)
489+
{
490+
const std::string expected_unix_socket_file = "expected file";
491+
const std::string expected_lockfile = "expected file.lock";
492+
493+
EXPECT_CALL(*m_mock_system_operations, unlink(StrEq(expected_unix_socket_file)));
494+
EXPECT_CALL(*m_mock_system_operations, unlink(StrEq(expected_lockfile)));
495+
496+
Connection_vio::unlink_unix_socket_file(expected_unix_socket_file);
497+
}
469498
}
470499
}

0 commit comments

Comments
 (0)