Skip to content

Commit c450fa4

Browse files
Grzegorz Szwarcbjornmu
authored andcommitted
Bug#22894429 Unable to uninstall mysqlx plugin
Issue: Unable to uninstall mysqlx plugin when the limit of available threads has been achived. Reviewed-by: Lukasz Kotula <[email protected]> Reviewed-by: Andrzej Religa <[email protected]> RB: 12072 (cherry picked from commit 41f85a0c5478e327f37cafa63ef1bb195d218671)
1 parent 9cb8e9c commit c450fa4

File tree

10 files changed

+90
-49
lines changed

10 files changed

+90
-49
lines changed

mysql-test/suite/xplugin/r/performance_schema.result

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ install plugin mysqlx soname "mysqlx.so";
22
call mtr.add_suppression("Plugin mysqlx reported: .Failed at SSL configuration: .SSL context is not usable without certificate and private key..");
33
call mtr.add_suppression("Plugin mysqlx reported: .SSL_CTX_load_verify_locations failed.");
44

5-
6 rows affected
6-
Rows matched: 6 Changed: 0 Warnings: 0
5+
7 rows affected
6+
Rows matched: 7 Changed: 0 Warnings: 0
77

88
1 rows affected
99
Rows matched: 1 Changed: 1 Warnings: 0
@@ -25,6 +25,7 @@ thread/mysqlx/acceptor_network
2525
0 rows affected
2626
name
2727
wait/synch/mutex/mysqlx/lock_list_access
28+
wait/synch/mutex/mysqlx/scheduler_dynamic_post
2829
wait/synch/mutex/mysqlx/scheduler_dynamic_task_pending
2930
wait/synch/mutex/mysqlx/scheduler_dynamic_thread_exit
3031
0 rows affected
@@ -39,6 +40,7 @@ NAME ENABLED TIMED
3940
wait/synch/mutex/mysqlx/lock_list_access NO NO
4041
wait/synch/mutex/mysqlx/scheduler_dynamic_task_pending NO NO
4142
wait/synch/mutex/mysqlx/scheduler_dynamic_thread_exit YES NO
43+
wait/synch/mutex/mysqlx/scheduler_dynamic_post YES NO
4244
wait/synch/rwlock/mysqlx/client_list_clients YES NO
4345
wait/synch/cond/mysqlx/scheduler_dynamic_task_pending NO NO
4446
wait/synch/cond/mysqlx/scheduler_dynamic_thread_exit YES NO
@@ -171,6 +173,7 @@ thread/mysqlx/acceptor_network
171173
command ok
172174
name
173175
wait/synch/mutex/mysqlx/lock_list_access
176+
wait/synch/mutex/mysqlx/scheduler_dynamic_post
174177
wait/synch/mutex/mysqlx/scheduler_dynamic_task_pending
175178
wait/synch/mutex/mysqlx/scheduler_dynamic_thread_exit
176179
command ok

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ namespace ngs
5252
virtual ~Scheduler_dynamic();
5353

5454
virtual void launch();
55-
virtual void set_num_workers(unsigned int n);
55+
virtual unsigned int set_num_workers(unsigned int n);
5656
virtual void stop();
5757
void set_idle_worker_timeout(unsigned long long milliseconds);
5858
bool post(Task* task);
@@ -65,6 +65,7 @@ namespace ngs
6565
void set_monitor(Monitor *monitor);
6666

6767
bool is_worker_thread(my_thread_t thread_id);
68+
bool is_running();
6869

6970
private:
7071
template<typename Element_type>
@@ -113,7 +114,7 @@ namespace ngs
113114
void* worker();
114115

115116
void create_thread();
116-
bool is_running();
117+
void create_min_num_workers();
117118

118119
int32 increase_workers_count();
119120
int32 decrease_workers_count();
@@ -125,6 +126,7 @@ namespace ngs
125126
Cond m_task_pending_cond;
126127
Mutex m_thread_exit_mutex;
127128
Cond m_thread_exit_cond;
129+
Mutex m_post_mutex;
128130
volatile int32 m_is_running;
129131
volatile int32 m_min_workers_count;
130132
volatile int32 m_workers_count;

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ namespace ngs
4646
typedef my_start_routine Start_routine_t;
4747
#endif
4848

49-
int thread_create(PSI_thread_key key, Thread_t *thread,
50-
const Thread_attr_t *attr,
51-
Start_routine_t func, void *arg);
49+
void thread_create(PSI_thread_key key, Thread_t *thread,
50+
const Thread_attr_t *attr,
51+
Start_routine_t func, void *arg);
5252
int thread_join(Thread_t *thread, void * *ret);
5353

5454
class Mutex

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

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Scheduler_dynamic::Scheduler_dynamic(const char* name)
4545
m_task_pending_cond(KEY_cond_x_scheduler_dynamic_task_pending),
4646
m_thread_exit_mutex(KEY_mutex_x_scheduler_dynamic_thread_exit),
4747
m_thread_exit_cond(KEY_cond_x_scheduler_dynamic_thread_exit),
48+
m_post_mutex(KEY_mutex_x_scheduler_dynamic_post),
4849
m_is_running(0),
4950
m_min_workers_count(1),
5051
m_workers_count(0),
@@ -65,27 +66,42 @@ void Scheduler_dynamic::launch()
6566
int32 int_0 = 0;
6667
if (my_atomic_cas32(&m_is_running, &int_0, 1))
6768
{
68-
set_num_workers(my_atomic_load32(&m_min_workers_count));
69+
create_min_num_workers();
6970
log_info("Scheduler \"%s\" started.", m_name.c_str());
7071
}
7172
}
7273

7374

74-
void Scheduler_dynamic::set_num_workers(unsigned int n)
75+
void Scheduler_dynamic::create_min_num_workers()
7576
{
76-
my_atomic_store32(&m_min_workers_count, n);
77-
7877
while (is_running() &&
79-
my_atomic_load32(&m_workers_count) <
80-
my_atomic_load32(&m_min_workers_count))
78+
my_atomic_load32(&m_workers_count) < my_atomic_load32(&m_min_workers_count))
8179
{
8280
create_thread();
8381
}
8482
}
8583

8684

87-
void Scheduler_dynamic::set_idle_worker_timeout(
88-
unsigned long long milliseconds)
85+
unsigned int Scheduler_dynamic::set_num_workers(unsigned int n)
86+
{
87+
my_atomic_store32(&m_min_workers_count, n);
88+
try
89+
{
90+
create_min_num_workers();
91+
}
92+
catch (std::exception &e)
93+
{
94+
log_debug("Exception in set minimal number of workers \"%s\"", e.what());
95+
const int32 m = my_atomic_load32(&m_workers_count);
96+
log_warning("Unable to set minimal number of workers to %u; actual value is %i", n, m);
97+
my_atomic_store32(&m_min_workers_count, m);
98+
return m;
99+
}
100+
return n;
101+
}
102+
103+
104+
void Scheduler_dynamic::set_idle_worker_timeout(unsigned long long milliseconds)
89105
{
90106
my_atomic_store64(&m_idle_worker_timeout, milliseconds);
91107
m_task_pending_cond.broadcast(m_task_pending_mutex);
@@ -131,45 +147,53 @@ bool Scheduler_dynamic::post(Task* task)
131147
if (is_running() == false || task == NULL)
132148
return false;
133149

150+
{
151+
Mutex_lock lock(m_post_mutex);
152+
153+
if (increase_tasks_count() >= my_atomic_load32(&m_workers_count))
154+
{
155+
try { create_thread(); }
156+
catch (std::exception &e)
157+
{
158+
log_error("Exception in post: %s", e.what());
159+
decrease_tasks_count();
160+
return false;
161+
}
162+
}
163+
}
164+
134165
while (m_tasks.push(task) == false) {}
135166
m_task_pending_cond.signal(m_task_pending_mutex);
136167

137-
if (increase_tasks_count() >= my_atomic_load32(&m_workers_count))
138-
create_thread();
139-
140168
return true;
141169
}
142170

143171

144172
bool Scheduler_dynamic::post(const Task& task)
145173
{
146-
if (is_running() == false || task == NULL)
147-
return false;
148-
149174
Task *copy_task = new (std::nothrow) Task(task);
150175

151-
if (NULL == copy_task)
152-
return false;
153-
154-
while (m_tasks.push(copy_task) == false) {}
155-
m_task_pending_cond.signal(m_task_pending_mutex);
156-
157-
if (increase_tasks_count() >= my_atomic_load32(&m_workers_count))
158-
create_thread();
176+
if (post(copy_task))
177+
return true;
159178

160-
return true;
179+
delete copy_task;
180+
return false;
161181
}
162182

183+
163184
bool Scheduler_dynamic::post_and_wait(const Task& task_to_be_posted)
164185
{
165186
Wait_for_signal future;
166187

167188
{
168189
ngs::Scheduler_dynamic::Task task = boost::bind(&Wait_for_signal::Signal_when_done::execute,
169-
boost::make_shared<ngs::Wait_for_signal::Signal_when_done>(boost::ref(future), task_to_be_posted));
190+
boost::make_shared<ngs::Wait_for_signal::Signal_when_done>(boost::ref(future), task_to_be_posted));
170191

171192
if (!post(task))
193+
{
194+
log_error("Internal error scheduling task");
172195
return false;
196+
}
173197
}
174198

175199
future.wait();
@@ -190,6 +214,7 @@ void *Scheduler_dynamic::worker_proxy(void *data)
190214
return reinterpret_cast<Scheduler_dynamic*>(data)->worker();
191215
}
192216

217+
193218
void *Scheduler_dynamic::worker()
194219
{
195220
bool worker_timed_out = false;
@@ -259,15 +284,8 @@ void Scheduler_dynamic::create_thread()
259284
if (is_running())
260285
{
261286
Thread_t thread;
262-
287+
ngs::thread_create(0, &thread, NULL, worker_proxy, this);
263288
increase_workers_count();
264-
265-
if (ngs::thread_create(0, &thread, NULL, worker_proxy, this) < 0)
266-
{
267-
decrease_workers_count();
268-
throw std::runtime_error("Could not create a worker thread.");
269-
}
270-
271289
m_threads.push(thread);
272290
}
273291
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@
2525
#include "ngs/thread.h"
2626

2727

28-
int ngs::thread_create(PSI_thread_key key, Thread_t *thread,
29-
const Thread_attr_t *attr,
30-
Start_routine_t func, void *arg)
28+
void ngs::thread_create(PSI_thread_key key, Thread_t *thread,
29+
const Thread_attr_t *attr,
30+
Start_routine_t func, void *arg)
3131
{
32-
return mysql_thread_create(key, thread, attr, func, arg);
32+
if (mysql_thread_create(key, thread, attr, func, arg))
33+
throw std::runtime_error("Could not create a thread");
3334
}
3435

3536

rapid/plugin/x/src/xpl_performance_schema.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ static PSI_thread_info all_x_threads[] = {
3636
PSI_mutex_key KEY_mutex_x_lock_list_access = PSI_NOT_INSTRUMENTED;
3737
PSI_mutex_key KEY_mutex_x_scheduler_dynamic_task_pending = PSI_NOT_INSTRUMENTED;
3838
PSI_mutex_key KEY_mutex_x_scheduler_dynamic_thread_exit = PSI_NOT_INSTRUMENTED;
39+
PSI_mutex_key KEY_mutex_x_scheduler_dynamic_post = PSI_NOT_INSTRUMENTED;
3940

4041
static PSI_mutex_info all_x_mutexes[] = {
4142
{ &KEY_mutex_x_lock_list_access, "lock_list_access", 0 },
4243
{ &KEY_mutex_x_scheduler_dynamic_task_pending, "scheduler_dynamic_task_pending", 0 },
4344
{ &KEY_mutex_x_scheduler_dynamic_thread_exit, "scheduler_dynamic_thread_exit", 0 },
45+
{ &KEY_mutex_x_scheduler_dynamic_post, "scheduler_dynamic_post", 0 }
4446
};
4547

4648
PSI_cond_key KEY_cond_x_scheduler_dynamic_task_pending = PSI_NOT_INSTRUMENTED;

rapid/plugin/x/src/xpl_performance_schema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ extern PSI_thread_key KEY_thread_x_acceptor;
3333
extern PSI_mutex_key KEY_mutex_x_lock_list_access;
3434
extern PSI_mutex_key KEY_mutex_x_scheduler_dynamic_task_pending;
3535
extern PSI_mutex_key KEY_mutex_x_scheduler_dynamic_thread_exit;
36+
extern PSI_mutex_key KEY_mutex_x_scheduler_dynamic_post;
3637

3738
extern PSI_cond_key KEY_cond_x_scheduler_dynamic_task_pending;
3839
extern PSI_cond_key KEY_cond_x_scheduler_dynamic_thread_exit;

rapid/plugin/x/src/xpl_server.cc

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,16 @@ bool xpl::Server::on_verify_server_state()
158158

159159
// closing clients has been moved to other thread
160160
// this thread have to gracefully shutdown io operations
161-
typedef ngs::Scheduler_dynamic::Task Task;
162-
Task *task = new Task(boost::bind(&ngs::Server::close_all_clients, &m_server));
163-
if (!m_wscheduler->post(task))
164-
delete task;
161+
if (m_wscheduler->is_running())
162+
{
163+
typedef ngs::Scheduler_dynamic::Task Task;
164+
Task *task = new Task(boost::bind(&ngs::Server::close_all_clients, &m_server));
165+
if (!m_wscheduler->post(task))
166+
{
167+
log_debug("Unable to schedule closing all clients ");
168+
delete task;
169+
}
170+
}
165171

166172
// stop the server, making the event loop stop looping around
167173
m_server.stop();
@@ -171,6 +177,7 @@ bool xpl::Server::on_verify_server_state()
171177
return true;
172178
}
173179

180+
174181
boost::shared_ptr<ngs::Client> xpl::Server::create_client(ngs::Connection_ptr connection)
175182
{
176183
return boost::make_shared<xpl::Client>(connection, &m_server, ++m_client_id, new xpl::Protocol_monitor());
@@ -216,6 +223,7 @@ void xpl::Server::did_accept_client(boost::shared_ptr<ngs::Client> client)
216223
Global_status_variables::instance().increment_accepted_connections_count();
217224
}
218225

226+
219227
void xpl::Server::did_reject_client(ngs::Server_delegate::Reject_reason reason)
220228
{
221229
switch (reason)
@@ -233,7 +241,10 @@ void xpl::Server::did_reject_client(ngs::Server_delegate::Reject_reason reason)
233241

234242
void xpl::Server::plugin_system_variables_changed()
235243
{
236-
m_wscheduler->set_num_workers(Plugin_system_variables::min_worker_threads);
244+
const unsigned int min = m_wscheduler->set_num_workers(Plugin_system_variables::min_worker_threads);
245+
if (min < Plugin_system_variables::min_worker_threads)
246+
Plugin_system_variables::min_worker_threads = min;
247+
237248
m_wscheduler->set_idle_worker_timeout(Plugin_system_variables::idle_worker_thread_timeout * 1000);
238249

239250
m_config->max_message_size = Plugin_system_variables::max_allowed_packet;
@@ -246,11 +257,13 @@ bool xpl::Server::is_terminating() const
246257
return mysqld::is_terminating();
247258
}
248259

260+
249261
bool xpl::Server::is_exiting()
250262
{
251263
return mysqld::is_terminating() || xpl::Server::exiting;
252264
}
253265

266+
254267
int xpl::Server::main(MYSQL_PLUGIN p)
255268
{
256269
xpl::plugin_handle = p;

rapid/unittest/gunit/xplugin/mock/session.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class Mock_scheduler_dynamic : public Scheduler_dynamic
5959
MOCK_METHOD0(stop, void());
6060
MOCK_METHOD0(thread_init, bool ());
6161
MOCK_METHOD0(thread_end, void ());
62-
MOCK_METHOD1(set_num_workers, void(unsigned int n));
62+
MOCK_METHOD1(set_num_workers, unsigned int(unsigned int n));
6363
};
6464

6565

rapid/unittest/gunit/xplugin/stubs/misc.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ PSI_mutex_key KEY_mutex_x_obuffer = PSI_NOT_INSTRUMENTED;
3434
PSI_mutex_key KEY_mutex_x_lock_list_access = PSI_NOT_INSTRUMENTED;
3535
PSI_mutex_key KEY_mutex_x_scheduler_dynamic_task_pending = PSI_NOT_INSTRUMENTED;
3636
PSI_mutex_key KEY_mutex_x_scheduler_dynamic_thread_exit = PSI_NOT_INSTRUMENTED;
37+
PSI_mutex_key KEY_mutex_x_scheduler_dynamic_post = PSI_NOT_INSTRUMENTED;
3738
PSI_mutex_key KEY_mutex_x_queue = PSI_NOT_INSTRUMENTED;
3839

3940
PSI_cond_key KEY_cond_x_scheduler_dynamic_task_pending = PSI_NOT_INSTRUMENTED;

0 commit comments

Comments
 (0)