Commit 60b76cd7 authored by Gleb Shchepa's avatar Gleb Shchepa

Bug #38883 (reopened): thd_security_context is not thread safe, crashes?

manual merge 5.0-->5.1, updating InnoDB plugin.
parents 0dde5599 ee136e3f
...@@ -376,6 +376,8 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length, ...@@ -376,6 +376,8 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
str.append(proc_info); str.append(proc_info);
} }
pthread_mutex_lock(&thd->LOCK_thd_data);
if (thd->query()) if (thd->query())
{ {
if (max_query_len < 1) if (max_query_len < 1)
...@@ -385,6 +387,9 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length, ...@@ -385,6 +387,9 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
str.append('\n'); str.append('\n');
str.append(thd->query(), len); str.append(thd->query(), len);
} }
pthread_mutex_unlock(&thd->LOCK_thd_data);
if (str.c_ptr_safe() == buffer) if (str.c_ptr_safe() == buffer)
return buffer; return buffer;
......
...@@ -770,35 +770,6 @@ convert_error_code_to_mysql( ...@@ -770,35 +770,6 @@ convert_error_code_to_mysql(
} }
} }
/*****************************************************************
If you want to print a thd that is not associated with the current thread,
you must call this function before reserving the InnoDB kernel_mutex, to
protect MySQL from setting thd->query NULL. If you print a thd of the current
thread, we know that MySQL cannot modify thd->query, and it is not necessary
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
the kernel_mutex.
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
function! */
extern "C"
void
innobase_mysql_prepare_print_arbitrary_thd(void)
/*============================================*/
{
VOID(pthread_mutex_lock(&LOCK_thread_count));
}
/*****************************************************************
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
function! */
extern "C"
void
innobase_mysql_end_print_arbitrary_thd(void)
/*========================================*/
{
VOID(pthread_mutex_unlock(&LOCK_thread_count));
}
/***************************************************************** /*****************************************************************
Prints info of a THD object (== user session thread) to the given file. Prints info of a THD object (== user session thread) to the given file.
NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for
......
...@@ -318,9 +318,7 @@ trx_commit_step( ...@@ -318,9 +318,7 @@ trx_commit_step(
/************************************************************************** /**************************************************************************
Prints info about a transaction to the given file. The caller must own the Prints info about a transaction to the given file. The caller must own the
kernel mutex and must have called kernel mutex. */
innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
or InnoDB cannot meanwhile change the info printed here. */
void void
trx_print( trx_print(
......
...@@ -22,31 +22,6 @@ Created 5/7/1996 Heikki Tuuri ...@@ -22,31 +22,6 @@ Created 5/7/1996 Heikki Tuuri
#include "trx0sys.h" #include "trx0sys.h"
/* 2 function prototypes copied from ha_innodb.cc: */
/*****************************************************************
If you want to print a thd that is not associated with the current thread,
you must call this function before reserving the InnoDB kernel_mutex, to
protect MySQL from setting thd->query NULL. If you print a thd of the current
thread, we know that MySQL cannot modify thd->query, and it is not necessary
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
the kernel_mutex.
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
function! */
void
innobase_mysql_prepare_print_arbitrary_thd(void);
/*============================================*/
/*****************************************************************
Relases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
function! */
void
innobase_mysql_end_print_arbitrary_thd(void);
/*========================================*/
/* Restricts the length of search we will do in the waits-for /* Restricts the length of search we will do in the waits-for
graph of transactions */ graph of transactions */
#define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
...@@ -4222,11 +4197,6 @@ lock_print_info_summary( ...@@ -4222,11 +4197,6 @@ lock_print_info_summary(
/*====================*/ /*====================*/
FILE* file) /* in: file where to print */ FILE* file) /* in: file where to print */
{ {
/* We must protect the MySQL thd->query field with a MySQL mutex, and
because the MySQL mutex must be reserved before the kernel_mutex of
InnoDB, we call innobase_mysql_prepare_print_arbitrary_thd() here. */
innobase_mysql_prepare_print_arbitrary_thd();
lock_mutex_enter_kernel(); lock_mutex_enter_kernel();
if (lock_deadlock_found) { if (lock_deadlock_found) {
...@@ -4314,7 +4284,6 @@ lock_print_info_all_transactions( ...@@ -4314,7 +4284,6 @@ lock_print_info_all_transactions(
if (trx == NULL) { if (trx == NULL) {
lock_mutex_exit_kernel(); lock_mutex_exit_kernel();
innobase_mysql_end_print_arbitrary_thd();
ut_ad(lock_validate()); ut_ad(lock_validate());
...@@ -4386,7 +4355,6 @@ lock_print_info_all_transactions( ...@@ -4386,7 +4355,6 @@ lock_print_info_all_transactions(
if (load_page_first) { if (load_page_first) {
lock_mutex_exit_kernel(); lock_mutex_exit_kernel();
innobase_mysql_end_print_arbitrary_thd();
mtr_start(&mtr); mtr_start(&mtr);
...@@ -4397,7 +4365,6 @@ lock_print_info_all_transactions( ...@@ -4397,7 +4365,6 @@ lock_print_info_all_transactions(
load_page_first = FALSE; load_page_first = FALSE;
innobase_mysql_prepare_print_arbitrary_thd();
lock_mutex_enter_kernel(); lock_mutex_enter_kernel();
goto loop; goto loop;
......
...@@ -1652,9 +1652,7 @@ trx_mark_sql_stat_end( ...@@ -1652,9 +1652,7 @@ trx_mark_sql_stat_end(
/************************************************************************** /**************************************************************************
Prints info about a transaction to the given file. The caller must own the Prints info about a transaction to the given file. The caller must own the
kernel mutex and must have called kernel mutex. */
innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
or InnoDB cannot meanwhile change the info printed here. */
void void
trx_print( trx_print(
......
...@@ -898,36 +898,6 @@ convert_error_code_to_mysql( ...@@ -898,36 +898,6 @@ convert_error_code_to_mysql(
} }
} }
/*************************************************************//**
If you want to print a thd that is not associated with the current thread,
you must call this function before reserving the InnoDB kernel_mutex, to
protect MySQL from setting thd->query NULL. If you print a thd of the current
thread, we know that MySQL cannot modify thd->query, and it is not necessary
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
the kernel_mutex. */
extern "C" UNIV_INTERN
void
innobase_mysql_prepare_print_arbitrary_thd(void)
/*============================================*/
{
ut_ad(!mutex_own(&kernel_mutex));
VOID(pthread_mutex_lock(&LOCK_thread_count));
}
/*************************************************************//**
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
In the InnoDB latching order, the mutex sits right above the
kernel_mutex. In debug builds, we assert that the kernel_mutex is
released before this function is invoked. */
extern "C" UNIV_INTERN
void
innobase_mysql_end_print_arbitrary_thd(void)
/*========================================*/
{
ut_ad(!mutex_own(&kernel_mutex));
VOID(pthread_mutex_unlock(&LOCK_thread_count));
}
/*************************************************************//** /*************************************************************//**
Prints info of a THD object (== user session thread) to the given file. */ Prints info of a THD object (== user session thread) to the given file. */
extern "C" UNIV_INTERN extern "C" UNIV_INTERN
......
...@@ -153,28 +153,6 @@ get_innobase_type_from_mysql_type( ...@@ -153,28 +153,6 @@ get_innobase_type_from_mysql_type(
const void* field) /*!< in: MySQL Field */ const void* field) /*!< in: MySQL Field */
__attribute__((nonnull)); __attribute__((nonnull));
/*************************************************************//**
If you want to print a thd that is not associated with the current thread,
you must call this function before reserving the InnoDB kernel_mutex, to
protect MySQL from setting thd->query NULL. If you print a thd of the current
thread, we know that MySQL cannot modify thd->query, and it is not necessary
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
the kernel_mutex. */
UNIV_INTERN
void
innobase_mysql_prepare_print_arbitrary_thd(void);
/*============================================*/
/*************************************************************//**
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
In the InnoDB latching order, the mutex sits right above the
kernel_mutex. In debug builds, we assert that the kernel_mutex is
released before this function is invoked. */
UNIV_INTERN
void
innobase_mysql_end_print_arbitrary_thd(void);
/*========================================*/
/******************************************************************//** /******************************************************************//**
Get the variable length bounds of the given character set. */ Get the variable length bounds of the given character set. */
UNIV_INTERN UNIV_INTERN
......
...@@ -338,9 +338,7 @@ trx_commit_step( ...@@ -338,9 +338,7 @@ trx_commit_step(
/**********************************************************************//** /**********************************************************************//**
Prints info about a transaction to the given file. The caller must own the Prints info about a transaction to the given file. The caller must own the
kernel mutex and must have called kernel mutex. */
innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
or InnoDB cannot meanwhile change the info printed here. */
UNIV_INTERN UNIV_INTERN
void void
trx_print( trx_print(
......
...@@ -4324,11 +4324,6 @@ lock_print_info_summary( ...@@ -4324,11 +4324,6 @@ lock_print_info_summary(
/*====================*/ /*====================*/
FILE* file) /*!< in: file where to print */ FILE* file) /*!< in: file where to print */
{ {
/* We must protect the MySQL thd->query field with a MySQL mutex, and
because the MySQL mutex must be reserved before the kernel_mutex of
InnoDB, we call innobase_mysql_prepare_print_arbitrary_thd() here. */
innobase_mysql_prepare_print_arbitrary_thd();
lock_mutex_enter_kernel(); lock_mutex_enter_kernel();
if (lock_deadlock_found) { if (lock_deadlock_found) {
...@@ -4411,7 +4406,6 @@ lock_print_info_all_transactions( ...@@ -4411,7 +4406,6 @@ lock_print_info_all_transactions(
if (trx == NULL) { if (trx == NULL) {
lock_mutex_exit_kernel(); lock_mutex_exit_kernel();
innobase_mysql_end_print_arbitrary_thd();
ut_ad(lock_validate()); ut_ad(lock_validate());
...@@ -4495,7 +4489,6 @@ lock_print_info_all_transactions( ...@@ -4495,7 +4489,6 @@ lock_print_info_all_transactions(
} }
lock_mutex_exit_kernel(); lock_mutex_exit_kernel();
innobase_mysql_end_print_arbitrary_thd();
mtr_start(&mtr); mtr_start(&mtr);
...@@ -4506,7 +4499,6 @@ lock_print_info_all_transactions( ...@@ -4506,7 +4499,6 @@ lock_print_info_all_transactions(
load_page_first = FALSE; load_page_first = FALSE;
innobase_mysql_prepare_print_arbitrary_thd();
lock_mutex_enter_kernel(); lock_mutex_enter_kernel();
goto loop; goto loop;
......
...@@ -1205,9 +1205,6 @@ trx_i_s_possibly_fetch_data_into_cache( ...@@ -1205,9 +1205,6 @@ trx_i_s_possibly_fetch_data_into_cache(
return(1); return(1);
} }
/* We are going to access trx->query in all transactions */
innobase_mysql_prepare_print_arbitrary_thd();
/* We need to read trx_sys and record/table lock queues */ /* We need to read trx_sys and record/table lock queues */
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
...@@ -1215,8 +1212,6 @@ trx_i_s_possibly_fetch_data_into_cache( ...@@ -1215,8 +1212,6 @@ trx_i_s_possibly_fetch_data_into_cache(
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
innobase_mysql_end_print_arbitrary_thd();
return(0); return(0);
} }
......
...@@ -1636,9 +1636,7 @@ trx_mark_sql_stat_end( ...@@ -1636,9 +1636,7 @@ trx_mark_sql_stat_end(
/**********************************************************************//** /**********************************************************************//**
Prints info about a transaction to the given file. The caller must own the Prints info about a transaction to the given file. The caller must own the
kernel mutex and must have called kernel mutex. */
innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
or InnoDB cannot meanwhile change the info printed here. */
UNIV_INTERN UNIV_INTERN
void void
trx_print( trx_print(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment