Skip to content

Commit e7b957c

Browse files
lthfacebook-github-bot
authored andcommitted
Use shared_ptr for ssl context objects
Summary: The upstream RCU lock implementation can lead to situations where the `ALTER INSTANCE RELOAD TLS` spins cpu at 100% for a long time. The solution to this is to use refcounting provided by `shared_ptr`. Fixes https://bugs.mysql.com/bug.php?id=107567 Reviewed By: hermanlee Differential Revision: D37188540 fbshipit-source-id: 37561bdcef56ae0cc1abbe63369baa7180938254
1 parent 92324e6 commit e7b957c

File tree

2 files changed

+38
-30
lines changed

2 files changed

+38
-30
lines changed

sql/ssl_acceptor_context_operator.cc

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
along with this program; if not, write to the Free Software
2121
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
2222

23+
#include "mutex_lock.h"
2324
#include "my_dbug.h" /* DBUG_ASSERT */
2425
#include "mysql/components/services/log_builtins.h" /* LogErr */
2526
#include "mysql/status_var.h" /* SHOW_VAR */
@@ -32,19 +33,19 @@ Ssl_acceptor_context_container *mysql_main;
3233
Ssl_acceptor_context_container *mysql_admin;
3334

3435
Ssl_acceptor_context_container::Ssl_acceptor_context_container(
35-
Ssl_acceptor_context_data *data)
36-
: lock_(nullptr) {
37-
lock_ = new Ssl_acceptor_context_data_lock(data);
36+
std::shared_ptr<Ssl_acceptor_context_data> &&data)
37+
: data_(data) {
38+
mysql_mutex_init(PSI_NOT_INSTRUMENTED, &mutex_, MY_MUTEX_INIT_FAST);
3839
}
3940

4041
Ssl_acceptor_context_container ::~Ssl_acceptor_context_container() {
41-
if (lock_ != nullptr) delete lock_;
42-
lock_ = nullptr;
42+
mysql_mutex_destroy(&mutex_);
4343
}
4444

4545
void Ssl_acceptor_context_container::switch_data(
46-
Ssl_acceptor_context_data *new_data) {
47-
if (lock_ != nullptr) lock_->write_wait_and_delete(new_data);
46+
std::shared_ptr<Ssl_acceptor_context_data> &&new_data) {
47+
MUTEX_LOCK(lock, &mutex_);
48+
data_ = new_data;
4849
}
4950

5051
bool TLS_channel::singleton_init(Ssl_acceptor_context_container **out,
@@ -67,10 +68,10 @@ bool TLS_channel::singleton_init(Ssl_acceptor_context_container **out,
6768
in auto-generation, bad key material explicitly specified or
6869
auto-generation disabled explcitly while SSL is still on.
6970
*/
70-
Ssl_acceptor_context_data *news =
71-
new Ssl_acceptor_context_data(channel, use_ssl_arg, callbacks);
71+
auto news = std::make_shared<Ssl_acceptor_context_data>(channel, use_ssl_arg,
72+
callbacks);
7273
Ssl_acceptor_context_container *new_container =
73-
new Ssl_acceptor_context_container(news);
74+
new Ssl_acceptor_context_container(std::move(news));
7475
if (news == nullptr || new_container == nullptr) {
7576
LogErr(WARNING_LEVEL, ER_SSL_LIBRARY_ERROR,
7677
"Error initializing the SSL context system structure");
@@ -101,29 +102,35 @@ void TLS_channel::singleton_flush(Ssl_acceptor_context_container *container,
101102
Ssl_init_callback *callbacks,
102103
enum enum_ssl_init_error *error, bool force) {
103104
if (container == nullptr) return;
104-
Ssl_acceptor_context_data *news =
105-
new Ssl_acceptor_context_data(channel, true, callbacks, false, error);
105+
auto news = std::make_shared<Ssl_acceptor_context_data>(
106+
channel, true, callbacks, false, error);
106107
if (*error != SSL_INITERR_NOERROR && !force) {
107-
delete news;
108108
return;
109109
}
110-
(void)container->switch_data(news);
110+
(void)container->switch_data(std::move(news));
111111
return;
112112
}
113113

114+
Lock_and_access_ssl_acceptor_context::Lock_and_access_ssl_acceptor_context(
115+
Ssl_acceptor_context_container *context) {
116+
// Take a reference
117+
MUTEX_LOCK(lock, &context->mutex_);
118+
data_ = context->data_;
119+
}
120+
114121
std::string Lock_and_access_ssl_acceptor_context::show_property(
115122
Ssl_acceptor_context_property_type property_type) {
116-
const Ssl_acceptor_context_data *data = read_lock_;
123+
const Ssl_acceptor_context_data *data = data_.get();
117124
return (data != nullptr ? data->show_property(property_type) : std::string{});
118125
}
119126

120127
std::string Lock_and_access_ssl_acceptor_context::channel_name() {
121-
const Ssl_acceptor_context_data *data = read_lock_;
128+
const Ssl_acceptor_context_data *data = data_.get();
122129
return (data != nullptr ? data->channel_name() : std::string{});
123130
}
124131

125132
bool Lock_and_access_ssl_acceptor_context::have_ssl() {
126-
const Ssl_acceptor_context_data *data = read_lock_;
133+
const Ssl_acceptor_context_data *data = data_.get();
127134
return (data != nullptr ? data->have_ssl() : false);
128135
}
129136

sql/ssl_acceptor_context_operator.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
#ifndef SSL_ACCEPTOR_CONTEXT_OPERATOR
2424
#define SSL_ACCEPTOR_CONTEXT_OPERATOR
2525

26+
#include <memory>
27+
2628
#include <my_rcu_lock.h> /* MyRcuLock */
29+
#include <mysql/psi/mysql_mutex.h>
2730
#include "sql/ssl_acceptor_context_data.h" /** Ssl_acceptor_context_data */
2831

2932
/* Types of supported contexts */
@@ -39,13 +42,13 @@ class TLS_channel;
3942
/** TLS context access protector */
4043
class Ssl_acceptor_context_container {
4144
protected:
42-
Ssl_acceptor_context_container(Ssl_acceptor_context_data *data);
45+
Ssl_acceptor_context_container(
46+
std::shared_ptr<Ssl_acceptor_context_data> &&data);
4347
~Ssl_acceptor_context_container();
44-
void switch_data(Ssl_acceptor_context_data *new_data);
45-
46-
using Ssl_acceptor_context_data_lock = MyRcuLock<Ssl_acceptor_context_data>;
48+
void switch_data(std::shared_ptr<Ssl_acceptor_context_data> &&new_data);
4749

48-
Ssl_acceptor_context_data_lock *lock_;
50+
std::shared_ptr<Ssl_acceptor_context_data> data_;
51+
mysql_mutex_t mutex_;
4952

5053
/* F.R.I.E.N.D.S. */
5154
friend class Lock_and_access_ssl_acceptor_context;
@@ -103,37 +106,36 @@ using Ssl_acceptor_context_data_lock = MyRcuLock<Ssl_acceptor_context_data>;
103106
/** TLS context access wrapper for ease of use */
104107
class Lock_and_access_ssl_acceptor_context {
105108
public:
106-
Lock_and_access_ssl_acceptor_context(Ssl_acceptor_context_container *context)
107-
: read_lock_(context->lock_) {}
109+
Lock_and_access_ssl_acceptor_context(Ssl_acceptor_context_container *context);
108110
~Lock_and_access_ssl_acceptor_context() {}
109111

110112
/** Access protected @ref Ssl_acceptor_context_data */
111113
operator const Ssl_acceptor_context_data *() {
112-
const Ssl_acceptor_context_data *c = read_lock_;
114+
const Ssl_acceptor_context_data *c = data_.get();
113115
return c;
114116
}
115117

116118
/**
117119
Access to the SSL_CTX from the protected @ref Ssl_acceptor_context_data
118120
*/
119121
operator SSL_CTX *() {
120-
const Ssl_acceptor_context_data *c = read_lock_;
122+
const Ssl_acceptor_context_data *c = data_.get();
121123
return c->ssl_acceptor_fd_->ssl_context;
122124
}
123125

124126
/**
125127
Access to the SSL from the protected @ref Ssl_acceptor_context_data
126128
*/
127129
operator SSL *() {
128-
const Ssl_acceptor_context_data *c = read_lock_;
130+
const Ssl_acceptor_context_data *c = data_.get();
129131
return c->acceptor_;
130132
}
131133

132134
/**
133135
Access to st_VioSSLFd from the protected @ref Ssl_acceptor_context_data
134136
*/
135137
operator struct st_VioSSLFd *() {
136-
const Ssl_acceptor_context_data *c = read_lock_;
138+
const Ssl_acceptor_context_data *c = data_.get();
137139
return c->ssl_acceptor_fd_;
138140
}
139141

@@ -163,8 +165,7 @@ class Lock_and_access_ssl_acceptor_context {
163165
bool have_ssl();
164166

165167
private:
166-
/** Read lock over TLS context */
167-
Ssl_acceptor_context_data_lock::ReadLock read_lock_;
168+
std::shared_ptr<Ssl_acceptor_context_data> data_;
168169
};
169170

170171
bool have_ssl();

0 commit comments

Comments
 (0)