--- mariadb-10.0.4-2/sql/sql_parse.cc 2013-08-18 06:53:52.778158175 -0300 +++ mariadb-10.0.4/sql/sql_parse.cc 2013-08-18 07:31:26.135170698 -0300 @@ -4178,7 +4178,7 @@ break; } - if (lex->kill_type == KILL_TYPE_ID) + if (lex->kill_type == KILL_TYPE_ID || lex->kill_type == KILL_TYPE_QUERY) { Item *it= (Item *)lex->value_list.head(); if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1)) @@ -7137,9 +7137,37 @@ return tmp; } +/** + Find a thread by query id and return it, locking it LOCK_thd_data + + @param id Identifier of the query id we're looking for + + @return NULL - not found + pointer - thread found, and its LOCK_thd_data is locked. +*/ + +THD *find_thread_by_query_id(ulong id) +{ + THD *tmp; + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list + I_List_iterator it(threads); + while ((tmp=it++)) + { + if (tmp->get_command() == COM_DAEMON) + continue; + if (tmp->query_id == id) + { + mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete + break; + } + } + mysql_mutex_unlock(&LOCK_thread_count); + return tmp; +} + /** - kill on thread. + kill one thread. @param thd Thread class @param id Thread id @@ -7195,6 +7223,64 @@ DBUG_RETURN(error); } +/** + kill one query. + + @param thd Thread class + @param id Query id + @param only_kill_query Should it kill the query or the connection + + @note + This is written such that we have a short lock on LOCK_thread_count +*/ + +uint kill_one_query(THD *thd, ulong id, killed_state kill_signal) +{ + /* based on kill_one_thread */ + THD *tmp; + uint error=ER_NO_SUCH_THREAD; /* TODO: maybe we could add a new err message for query id? */ + DBUG_ENTER("kill_one_query"); + DBUG_PRINT("enter", ("id: %lu signal: %u", id, (uint) kill_signal)); + + if ((tmp= find_thread_by_query_id(id))) + { + /* + If we're SUPER, we can KILL anything, including system-threads. + No further checks. + + KILLer: thd->security_ctx->user could in theory be NULL while + we're still in "unauthenticated" state. This is a theoretical + case (the code suggests this could happen, so we play it safe). + + KILLee: tmp->security_ctx->user will be NULL for system threads. + We need to check so Jane Random User doesn't crash the server + when trying to kill a) system threads or b) unauthenticated users' + threads (Bug#43748). + + If user of both killer and killee are non-NULL, proceed with + slayage if both are string-equal. + + It's ok to also kill DELAYED threads with KILL_CONNECTION instead of + KILL_SYSTEM_THREAD; The difference is that KILL_CONNECTION may be + faster and do a harder kill than KILL_SYSTEM_THREAD; + */ + + if ((thd->security_ctx->master_access & SUPER_ACL) || + thd->security_ctx->user_matches(tmp->security_ctx)) + { + if ((kill_signal & KILL_IF_IDLE)!=0 || + tmp->get_command() == COM_SLEEP) + tmp->awake(kill_signal); + error=0; + } + else + error=ER_KILL_DENIED_ERROR; + mysql_mutex_unlock(&tmp->LOCK_thd_data); + } + DBUG_PRINT("exit", ("%d", error)); + DBUG_RETURN(error); +} + /** kill all threads from one user @@ -7282,7 +7368,7 @@ SYNOPSIS sql_kill() thd Thread class - id Thread id + id Thread id (or QUERY ID, based on thd->lex->kill_type == KILL_TYPE_QUERY) only_kill_query Should it kill the query or the connection */ @@ -7290,7 +7376,12 @@ void sql_kill(THD *thd, ulong id, killed_state state) { uint error; - if (!(error= kill_one_thread(thd, id, state))) + if(thd->lex->kill_type == KILL_TYPE_QUERY) + error= kill_one_query(thd, id, state); + else + error= kill_one_thread(thd, id, state); + + if (!error) { if ((!thd->killed)) my_ok(thd);