mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Avoiding a theoretically possible crash (pthread_mutex_lock(0)) which could (at least in POSIX Threads books)
happen on SMP machines, when a thread is going to wait on a condition and it is KILLed at the same time. Cleaning code a bit by adding a test in enter_cond() that we have the mutex (was already the case in all places where it's called except one which is fixed here).
This commit is contained in:
@ -1544,7 +1544,6 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
|
|||||||
|
|
||||||
void MYSQL_LOG:: wait_for_update(THD* thd, bool master_or_slave)
|
void MYSQL_LOG:: wait_for_update(THD* thd, bool master_or_slave)
|
||||||
{
|
{
|
||||||
safe_mutex_assert_owner(&LOCK_log);
|
|
||||||
const char* old_msg = thd->enter_cond(&update_cond, &LOCK_log,
|
const char* old_msg = thd->enter_cond(&update_cond, &LOCK_log,
|
||||||
master_or_slave ?
|
master_or_slave ?
|
||||||
"Has read all relay log; waiting for \
|
"Has read all relay log; waiting for \
|
||||||
|
@ -588,6 +588,7 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock,
|
|||||||
while (start_id == *slave_run_id)
|
while (start_id == *slave_run_id)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("sleep",("Waiting for slave thread to start"));
|
DBUG_PRINT("sleep",("Waiting for slave thread to start"));
|
||||||
|
pthread_mutex_lock(cond_lock);
|
||||||
const char* old_msg = thd->enter_cond(start_cond,cond_lock,
|
const char* old_msg = thd->enter_cond(start_cond,cond_lock,
|
||||||
"Waiting for slave thread to start");
|
"Waiting for slave thread to start");
|
||||||
pthread_cond_wait(start_cond,cond_lock);
|
pthread_cond_wait(start_cond,cond_lock);
|
||||||
|
@ -299,8 +299,18 @@ void THD::awake(bool prepare_to_die)
|
|||||||
exits the cond in the time between read and broadcast, but that is
|
exits the cond in the time between read and broadcast, but that is
|
||||||
ok since all we want to do is to make the victim thread get out
|
ok since all we want to do is to make the victim thread get out
|
||||||
of waiting on current_cond.
|
of waiting on current_cond.
|
||||||
|
If we see a non-zero current_cond: it cannot be an old value (because
|
||||||
|
then exit_cond() should have run and it can't because we have mutex); so
|
||||||
|
it is the true value but maybe current_mutex is not yet non-zero (we're
|
||||||
|
in the middle of enter_cond() and there is a "memory order
|
||||||
|
inversion"). So we test the mutex too to not lock 0.
|
||||||
|
Note that there is a small chance we fail to kill. If victim has locked
|
||||||
|
current_mutex, and hasn't entered enter_cond(), then we don't know it's
|
||||||
|
going to wait on cond. Then victim goes into its cond "forever" (until
|
||||||
|
we issue a second KILL). True we have set its thd->killed but it may not
|
||||||
|
see it immediately and so may have time to reach the cond_wait().
|
||||||
*/
|
*/
|
||||||
if (mysys_var->current_cond)
|
if (mysys_var->current_cond && mysys_var->current_mutex)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(mysys_var->current_mutex);
|
pthread_mutex_lock(mysys_var->current_mutex);
|
||||||
pthread_cond_broadcast(mysys_var->current_cond);
|
pthread_cond_broadcast(mysys_var->current_cond);
|
||||||
|
@ -539,6 +539,7 @@ public:
|
|||||||
const char* msg)
|
const char* msg)
|
||||||
{
|
{
|
||||||
const char* old_msg = proc_info;
|
const char* old_msg = proc_info;
|
||||||
|
safe_mutex_assert_owner(mutex);
|
||||||
mysys_var->current_mutex = mutex;
|
mysys_var->current_mutex = mutex;
|
||||||
mysys_var->current_cond = cond;
|
mysys_var->current_cond = cond;
|
||||||
proc_info = msg;
|
proc_info = msg;
|
||||||
|
Reference in New Issue
Block a user