Skip to content

Commit

Permalink
MDEV-15359 Thread stay in "cleaning up" status after finishing
Browse files Browse the repository at this point in the history
make thd_get_error_context_description() to show not just
thd->proc_info, but exactly the same thread state that SHOW PROCESSLIST
shows.
  • Loading branch information
vuvova committed Jun 13, 2018
1 parent d2e1ed8 commit 51254da
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 97 deletions.
8 changes: 8 additions & 0 deletions mysql-test/suite/plugins/r/processlist.result
@@ -0,0 +1,8 @@
create table t1 (a int) engine=innodb;
start transaction;
insert t1 values (1);
state from show engine innodb status

state from show processlist

drop table t1;
18 changes: 18 additions & 0 deletions mysql-test/suite/plugins/t/processlist.test
@@ -0,0 +1,18 @@
#
# MDEV-15359 Thread stay in "cleaning up" status after finishing
#
source include/have_innodb.inc;

create table t1 (a int) engine=innodb;
start transaction;
insert t1 values (1);
let id=`select connection_id()`;
connect con2,localhost,root;
let s=query_get_value(show engine innodb status,Status,1);
disable_query_log;
eval select regexp_replace("$s", '(?s)^.*MySQL thread id $id,.*root([^\n]*)\n.*', '\\\\1') as `state from show engine innodb status`;
eval select state as `state from show processlist` from information_schema.processlist where id = $id;
enable_query_log;
disconnect con2;
connection default;
drop table t1;
97 changes: 0 additions & 97 deletions sql/sql_class.cc
Expand Up @@ -717,103 +717,6 @@ extern "C"
}


/**
Dumps a text description of a thread, its security context
(user, host) and the current query.
@param thd thread context
@param buffer pointer to preferred result buffer
@param length length of buffer
@param max_query_len how many chars of query to copy (0 for all)
@return Pointer to string
*/

extern "C"
char *thd_get_error_context_description(THD *thd, char *buffer,
unsigned int length,
unsigned int max_query_len)
{
String str(buffer, length, &my_charset_latin1);
const Security_context *sctx= &thd->main_security_ctx;
char header[256];
int len;

mysql_mutex_lock(&LOCK_thread_count);

/*
The pointers thd->query and thd->proc_info might change since they are
being modified concurrently. This is acceptable for proc_info since its
values doesn't have to very accurate and the memory it points to is static,
but we need to attempt a snapshot on the pointer values to avoid using NULL
values. The pointer to thd->query however, doesn't point to static memory
and has to be protected by thd->LOCK_thd_data or risk pointing to
uninitialized memory.
*/
const char *proc_info= thd->proc_info;

len= my_snprintf(header, sizeof(header),
"MySQL thread id %lu, OS thread handle 0x%lx, query id %lu",
thd->thread_id, (ulong) thd->real_id, (ulong) thd->query_id);
str.length(0);
str.append(header, len);

if (sctx->host)
{
str.append(' ');
str.append(sctx->host);
}

if (sctx->ip)
{
str.append(' ');
str.append(sctx->ip);
}

if (sctx->user)
{
str.append(' ');
str.append(sctx->user);
}

if (proc_info)
{
str.append(' ');
str.append(proc_info);
}

/* Don't wait if LOCK_thd_data is used as this could cause a deadlock */
if (!mysql_mutex_trylock(&thd->LOCK_thd_data))
{
if (thd->query())
{
if (max_query_len < 1)
len= thd->query_length();
else
len= MY_MIN(thd->query_length(), max_query_len);
str.append('\n');
str.append(thd->query(), len);
}
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
mysql_mutex_unlock(&LOCK_thread_count);

if (str.c_ptr_safe() == buffer)
return buffer;

/*
We have to copy the new string to the destination buffer because the string
was reallocated to a larger buffer to be able to fit.
*/
DBUG_ASSERT(buffer != NULL);
length= MY_MIN(str.length(), length-1);
memcpy(buffer, str.c_ptr_quick(), length);
/* Make sure that the new string is null terminated */
buffer[length]= '\0';
return buffer;
}


#if MARIA_PLUGIN_INTERFACE_VERSION < 0x0200
/**
TODO: This function is for API compatibility, remove it eventually.
Expand Down
85 changes: 85 additions & 0 deletions sql/sql_show.cc
Expand Up @@ -9773,3 +9773,88 @@ static void get_cs_converted_string_value(THD *thd,
return;
}
#endif

/**
Dumps a text description of a thread, its security context
(user, host) and the current query.
@param thd thread context
@param buffer pointer to preferred result buffer
@param length length of buffer
@param max_query_len how many chars of query to copy (0 for all)
@return Pointer to string
*/

extern "C"
char *thd_get_error_context_description(THD *thd, char *buffer,
unsigned int length,
unsigned int max_query_len)
{
String str(buffer, length, &my_charset_latin1);
const Security_context *sctx= &thd->main_security_ctx;
char header[256];
int len;

mysql_mutex_lock(&LOCK_thread_count);

len= my_snprintf(header, sizeof(header),
"MySQL thread id %lu, OS thread handle 0x%lx, query id %lu",
thd->thread_id, (ulong) thd->real_id, (ulong) thd->query_id);
str.length(0);
str.append(header, len);

if (sctx->host)
{
str.append(' ');
str.append(sctx->host);
}

if (sctx->ip)
{
str.append(' ');
str.append(sctx->ip);
}

if (sctx->user)
{
str.append(' ');
str.append(sctx->user);
}

/* Don't wait if LOCK_thd_data is used as this could cause a deadlock */
if (!mysql_mutex_trylock(&thd->LOCK_thd_data))
{
if (const char *info= thread_state_info(thd))
{
str.append(' ');
str.append(info);
}

if (thd->query())
{
if (max_query_len < 1)
len= thd->query_length();
else
len= MY_MIN(thd->query_length(), max_query_len);
str.append('\n');
str.append(thd->query(), len);
}
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
mysql_mutex_unlock(&LOCK_thread_count);

if (str.c_ptr_safe() == buffer)
return buffer;

/*
We have to copy the new string to the destination buffer because the string
was reallocated to a larger buffer to be able to fit.
*/
DBUG_ASSERT(buffer != NULL);
length= MY_MIN(str.length(), length-1);
memcpy(buffer, str.c_ptr_quick(), length);
/* Make sure that the new string is null terminated */
buffer[length]= '\0';
return buffer;
}

0 comments on commit 51254da

Please sign in to comment.