From: Gleb Shchepa Date: July 23 2009 2:53pm Subject: bzr commit into mysql-5.0-bugteam branch (gshchepa:2789) Bug#38816 List-Archive: http://lists.mysql.com/commits/79202 X-Bug: 38816 Message-Id: <20090723145436.35E494560EF@localhost.localdomain> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_3h9qRJt4TkS6zZiFiSZFYw)" --Boundary_(ID_3h9qRJt4TkS6zZiFiSZFYw) MIME-version: 1.0 Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-disposition: inline #At file:///home/uchum/work/bzr/38816-5.0/ based on revid:epotemkin@stripped 2789 Gleb Shchepa 2009-07-23 Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! The problem of that bugreport was mostly fixed by the patch for bug 38691. However, attached test case focused on another crash or valgrind warning problem: SHOW PROCESSLIST query accesses freed memory of SP instruction that run in a parallel connection. Changes of thd->query/thd->query_length in dangerous places have been guarded with the per-thread LOCK_thd_data mutex (the THD::LOCK_delete mutex has been renamed to THD::LOCK_thd_data). @ sql/ha_myisam.cc Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! Modification of THD::query/query_length has been guarded with the a THD::set_query() method call/LOCK_thd_data mutex. Unnecessary locking with the global LOCK_thread_count mutex has been removed. @ sql/log_event.cc Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! Modification of THD::query/query_length has been guarded with the THD::set_query()) method call/LOCK_thd_data mutex. @ sql/slave.cc Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! Modification of THD::query/query_length has been guarded with the THD::set_query() method call/LOCK_thd_data mutex. The THD::LOCK_delete mutex has been renamed to THD::LOCK_thd_data. @ sql/sp_head.cc Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! Modification of THD::query/query_length has been guarded with the a THD::set_query() method call/LOCK_thd_data mutex. @ sql/sql_class.cc Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! The new THD::LOCK_thd_data mutex and THD::set_query() method has been added to guard modifications of THD::query/ THD::query_length fields, also the Statement::set_statement() method has been overloaded in the THD class. The THD::LOCK_delete mutex has been renamed to THD::LOCK_thd_data. @ sql/sql_class.h Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! The new THD::LOCK_thd_data mutex and THD::set_query() method has been added to guard modifications of THD::query/ THD::query_length fields, also the Statement::set_statement() method has been overloaded in the THD class. The THD::LOCK_delete mutex has been renamed to THD::LOCK_thd_data. @ sql/sql_insert.cc Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! Modification of THD::query/query_length has been guarded with the a THD::set_query() method call/LOCK_thd_data mutex. @ sql/sql_parse.cc Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! Modification of THD::query/query_length has been guarded with the a THD::set_query() method call/LOCK_thd_data mutex. @ sql/sql_repl.cc Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! The THD::LOCK_delete mutex has been renamed to THD::LOCK_thd_data. @ sql/sql_show.cc Bug #38816: kill + flush tables with read lock + stored procedures causes crashes! Inter-thread read of THD::query/query_length field has been protected with a new per-thread LOCK_thd_data mutex in the mysqld_list_processes function. modified: sql/ha_myisam.cc sql/log_event.cc sql/slave.cc sql/sp_head.cc sql/sql_class.cc sql/sql_class.h sql/sql_insert.cc sql/sql_parse.cc sql/sql_repl.cc sql/sql_show.cc === modified file 'sql/ha_myisam.cc' --- a/sql/ha_myisam.cc 2009-06-29 13:17:01 +0000 +++ b/sql/ha_myisam.cc 2009-07-23 14:53:26 +0000 @@ -1487,10 +1487,8 @@ bool ha_myisam::check_and_repair(THD *th old_query= thd->query; old_query_length= thd->query_length; - pthread_mutex_lock(&LOCK_thread_count); - thd->query= (char*) table->s->table_name; - thd->query_length= (uint32) strlen(table->s->table_name); - pthread_mutex_unlock(&LOCK_thread_count); + thd->set_query((char*) table->s->table_name, + (uint32) strlen(table->s->table_name)); if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt)) { @@ -1503,10 +1501,7 @@ bool ha_myisam::check_and_repair(THD *th if (repair(thd, &check_opt)) error=1; } - pthread_mutex_lock(&LOCK_thread_count); - thd->query= old_query; - thd->query_length= old_query_length; - pthread_mutex_unlock(&LOCK_thread_count); + thd->set_query(old_query, old_query_length); DBUG_RETURN(error); } === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2009-06-29 13:17:01 +0000 +++ b/sql/log_event.cc 2009-07-23 14:53:26 +0000 @@ -1960,8 +1960,7 @@ int Query_log_event::exec_event(struct s db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { thd->set_time((time_t)when); - thd->query_length= q_len_arg; - thd->query= (char*)query_arg; + thd->set_query((char*)query_arg, q_len_arg); VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id = next_query_id(); VOID(pthread_mutex_unlock(&LOCK_thread_count)); @@ -2164,7 +2163,6 @@ Default database: '%s'. Query: '%s'", } /* End of if (db_ok(... */ end: - VOID(pthread_mutex_lock(&LOCK_thread_count)); /* Probably we have set thd->query, thd->db, thd->catalog to point to places in the data_buf of this event. Now the event is going to be deleted @@ -2177,10 +2175,8 @@ end: */ thd->catalog= 0; thd->set_db(NULL, 0); /* will free the current database */ + thd->set_query(NULL, 0); DBUG_PRINT("info", ("end: query= 0")); - thd->query= 0; // just to be sure - thd->query_length= 0; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); close_thread_tables(thd); free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); /* @@ -3259,8 +3255,7 @@ int Load_log_event::exec_event(NET* net, print_query(FALSE, load_data_query, &end, (char **)&thd->lex->fname_start, (char **)&thd->lex->fname_end); *end= 0; - thd->query_length= (uint) (end - load_data_query); - thd->query= load_data_query; + thd->set_query(load_data_query, (uint) (end - load_data_query)); if (sql_ex.opt_flags & REPLACE_FLAG) { @@ -3366,12 +3361,9 @@ int Load_log_event::exec_event(NET* net, error: thd->net.vio = 0; const char *remember_db= thd->db; - VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->catalog= 0; thd->set_db(NULL, 0); /* will free the current database */ - thd->query= 0; - thd->query_length= 0; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + thd->set_query(NULL, 0); close_thread_tables(thd); if (thd->query_error) { === modified file 'sql/slave.cc' --- a/sql/slave.cc 2009-06-29 13:17:01 +0000 +++ b/sql/slave.cc 2009-07-23 14:53:26 +0000 @@ -755,7 +755,7 @@ int terminate_slave_thread(THD* thd, int error; DBUG_PRINT("loop", ("killing slave thread")); - pthread_mutex_lock(&thd->LOCK_delete); + pthread_mutex_lock(&thd->LOCK_thd_data); #ifndef DONT_USE_THR_ALARM /* Error codes from pthread_kill are: @@ -766,7 +766,7 @@ int terminate_slave_thread(THD* thd, DBUG_ASSERT(err != EINVAL); #endif thd->awake(THD::NOT_KILLED); - pthread_mutex_unlock(&thd->LOCK_delete); + pthread_mutex_unlock(&thd->LOCK_thd_data); /* There is a small chance that slave thread might miss the first @@ -1608,15 +1608,13 @@ static int create_table_from_dump(THD* t DBUG_RETURN(1); } thd->command = COM_TABLE_DUMP; - thd->query_length= packet_len; - /* Note that we should not set thd->query until the area is initalized */ if (!(query = thd->strmake((char*) net->read_pos, packet_len))) { sql_print_error("create_table_from_dump: out of memory"); my_message(ER_GET_ERRNO, "Out of memory", MYF(0)); DBUG_RETURN(1); } - thd->query= query; + thd->set_query(query, packet_len); thd->query_error = 0; thd->net.no_send_ok = 1; @@ -3867,11 +3865,8 @@ err: // print the current replication position sql_print_information("Slave I/O thread exiting, read up to log '%s', position %s", IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff)); - VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query= 0; // extra safety - thd->query_length= 0; + thd->set_query(NULL, 0); thd->reset_db(NULL, 0); - VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (mysql) { /* @@ -4105,17 +4100,14 @@ the slave SQL thread with \"SLAVE START\ RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff)); err: - VOID(pthread_mutex_lock(&LOCK_thread_count)); /* Some extra safety, which should not been needed (normally, event deletion should already have done these assignments (each event which sets these variables is supposed to set them to 0 before terminating)). */ - thd->catalog= 0; + thd->catalog= 0; + thd->set_query(NULL, 0); thd->reset_db(NULL, 0); - thd->query= 0; - thd->query_length= 0; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd_proc_info(thd, "Waiting for slave mutex on exit"); pthread_mutex_lock(&rli->run_lock); /* We need data_lock, at least to wake up any waiting master_pos_wait() */ === modified file 'sql/sp_head.cc' --- a/sql/sp_head.cc 2009-05-06 13:06:32 +0000 +++ b/sql/sp_head.cc 2009-07-23 14:53:26 +0000 @@ -949,8 +949,7 @@ subst_spvars(THD *thd, sp_instr *instr, else DBUG_RETURN(TRUE); - thd->query= pbuf; - thd->query_length= qbuf.length(); + thd->set_query(pbuf, qbuf.length()); DBUG_RETURN(FALSE); } @@ -2654,8 +2653,7 @@ sp_instr_stmt::execute(THD *thd, uint *n } else *nextp= m_ip+1; - thd->query= query; - thd->query_length= query_length; + thd->set_query(query, query_length); thd->query_name_consts= 0; } DBUG_RETURN(res); === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2009-06-11 11:49:04 +0000 +++ b/sql/sql_class.cc 2009-07-23 14:53:26 +0000 @@ -259,7 +259,7 @@ THD::THD() #ifdef SIGNAL_WITH_VIO_CLOSE active_vio = 0; #endif - pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&LOCK_thd_data, MY_MUTEX_INIT_FAST); /* Variables with default values */ proc_info="login"; @@ -486,8 +486,8 @@ THD::~THD() THD_CHECK_SENTRY(this); DBUG_ENTER("~THD()"); /* Ensure that no one is using THD */ - pthread_mutex_lock(&LOCK_delete); - pthread_mutex_unlock(&LOCK_delete); + pthread_mutex_lock(&LOCK_thd_data); + pthread_mutex_unlock(&LOCK_thd_data); add_to_status(&global_status_var, &status_var); /* Close connection */ @@ -513,7 +513,7 @@ THD::~THD() free_root(&transaction.mem_root,MYF(0)); #endif mysys_var=0; // Safety (shouldn't be needed) - pthread_mutex_destroy(&LOCK_delete); + pthread_mutex_destroy(&LOCK_thd_data); #ifndef DBUG_OFF dbug_sentry= THD_SENTRY_GONE; #endif @@ -551,7 +551,7 @@ void add_to_status(STATUS_VAR *to_var, S void THD::awake(THD::killed_state state_to_set) { THD_CHECK_SENTRY(this); - safe_mutex_assert_owner(&LOCK_delete); + safe_mutex_assert_owner(&LOCK_thd_data); killed= state_to_set; if (state_to_set != THD::KILL_QUERY) @@ -895,7 +895,7 @@ int THD::send_explain_fields(select_resu void THD::close_active_vio() { DBUG_ENTER("close_active_vio"); - safe_mutex_assert_owner(&LOCK_delete); + safe_mutex_assert_owner(&LOCK_thd_data); #ifndef EMBEDDED_LIBRARY if (active_vio) { @@ -2323,6 +2323,25 @@ void THD::restore_sub_statement_state(Su } +void THD::set_statement(Statement *stmt) +{ + pthread_mutex_lock(&LOCK_thd_data); + Statement::set_statement(stmt); + pthread_mutex_unlock(&LOCK_thd_data); +} + + +/** Assign a new value to thd->query. */ + +void THD::set_query(char *query_arg, uint32 query_length_arg) +{ + pthread_mutex_lock(&LOCK_thd_data); + query= query_arg; + query_length= query_length_arg; + pthread_mutex_unlock(&LOCK_thd_data); +} + + /** Mark transaction to rollback and mark error as fatal to a sub-statement. === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2009-06-11 11:49:04 +0000 +++ b/sql/sql_class.h 2009-07-23 14:53:26 +0000 @@ -835,22 +835,16 @@ public: we need to declare it char * because all table handlers are written in C and need to point to it. - Note that (A) if we set query = NULL, we must at the same time set - query_length = 0, and protect the whole operation with the - LOCK_thread_count mutex. And (B) we are ONLY allowed to set query to a - non-NULL value if its previous value is NULL. We do not need to protect - operation (B) with any mutex. To avoid crashes in races, if we do not - know that thd->query cannot change at the moment, one should print + Note that if we set query = NULL, we must at the same time set + query_length = 0, and protect the whole operation with + LOCK_thd_data mutex. To avoid crashes in races, if we do not + know that thd->query cannot change at the moment, we should print thd->query like this: - (1) reserve the LOCK_thread_count mutex; - (2) check if thd->query is NULL; - (3) if not NULL, then print at most thd->query_length characters from - it. We will see the query_length field as either 0, or the right value - for it. - Assuming that the write and read of an n-bit memory field in an n-bit - computer is atomic, we can avoid races in the above way. - This printing is needed at least in SHOW PROCESSLIST and SHOW INNODB - STATUS. + (1) reserve the LOCK_thd_data mutex; + (2) print or copy the value of query and query_length + (3) release LOCK_thd_data mutex. + This printing is needed at least in SHOW PROCESSLIST and SHOW + ENGINE INNODB STATUS. */ char *query; uint32 query_length; // current query length @@ -866,7 +860,7 @@ public: virtual ~Statement(); /* Assign execution context (note: not all members) of given stmt to self */ - void set_statement(Statement *stmt); + virtual void set_statement(Statement *stmt); void set_n_backup_statement(Statement *stmt, Statement *backup); void restore_backup_statement(Statement *stmt, Statement *backup); /* return class type */ @@ -1229,7 +1223,15 @@ public: THR_LOCK_OWNER main_lock_id; // To use for conventional queries THR_LOCK_OWNER *lock_id; // If not main_lock_id, points to // the lock_id of a cursor. - pthread_mutex_t LOCK_delete; // Locked before thd is deleted + /** + Protects THD data accessed from other threads: + - thd->query and thd->query_length (used by SHOW ENGINE + INNODB STATUS and SHOW PROCESSLIST + - thd->mysys_var (used by KILL statement and shutdown). + Is locked when THD is deleted. + */ + pthread_mutex_t LOCK_thd_data; + /* all prepared statements and cursors of this connection */ Statement_map stmt_map; /* @@ -1637,15 +1639,15 @@ public: #ifdef SIGNAL_WITH_VIO_CLOSE inline void set_active_vio(Vio* vio) { - pthread_mutex_lock(&LOCK_delete); + pthread_mutex_lock(&LOCK_thd_data); active_vio = vio; - pthread_mutex_unlock(&LOCK_delete); + pthread_mutex_unlock(&LOCK_thd_data); } inline void clear_active_vio() { - pthread_mutex_lock(&LOCK_delete); + pthread_mutex_lock(&LOCK_thd_data); active_vio = 0; - pthread_mutex_unlock(&LOCK_delete); + pthread_mutex_unlock(&LOCK_thd_data); } void close_active_vio(); #endif @@ -1882,6 +1884,14 @@ public: */ void pop_internal_handler(); + /** Overloaded to guard query/query_length fields */ + virtual void set_statement(Statement *stmt); + + /** + Assign a new value to thd->query. + Protected with LOCK_thd_data mutex. + */ + void set_query(char *query_arg, uint32 query_length_arg); private: /** The current internal error handler for this thread, or NULL. */ Internal_error_handler *m_internal_handler; === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2009-07-03 08:35:00 +0000 +++ b/sql/sql_insert.cc 2009-07-23 14:53:26 +0000 @@ -1854,7 +1854,7 @@ bool delayed_get_table(THD *thd, TABLE_L thread_count++; pthread_mutex_unlock(&LOCK_thread_count); di->thd.set_db(table_list->db, (uint) strlen(table_list->db)); - di->thd.query= my_strdup(table_list->table_name, MYF(MY_WME)); + di->thd.set_query(my_strdup(table_list->table_name, MYF(MY_WME)), 0); if (di->thd.db == NULL || di->thd.query == NULL) { /* The error is reported */ === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2009-07-16 12:37:38 +0000 +++ b/sql/sql_parse.cc 2009-07-23 14:53:26 +0000 @@ -1106,8 +1106,7 @@ void execute_init_command(THD *thd, sys_ values of init_command_var can't be changed */ rw_rdlock(var_mutex); - thd->query= init_command_var->value; - thd->query_length= init_command_var->value_length; + thd->set_query(init_command_var->value, init_command_var->value_length); save_client_capabilities= thd->client_capabilities; thd->client_capabilities|= CLIENT_MULTI_QUERIES; /* @@ -1326,6 +1325,7 @@ pthread_handler_t handle_bootstrap(void thd->init_for_queries(); while (fgets(buff, thd->net.max_packet, file)) { + char *query; ulong length= (ulong) strlen(buff); while (buff[length-1] != '\n' && !feof(file)) { @@ -1350,10 +1350,9 @@ pthread_handler_t handle_bootstrap(void buff[length-1] == ';')) length--; buff[length]=0; - thd->query_length=length; - thd->query= thd->memdup_w_gap(buff, length+1, - thd->db_length+1+QUERY_CACHE_FLAGS_SIZE); - thd->query[length] = '\0'; + query= thd->memdup_w_gap(buff, length + 1, + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE); + thd->set_query(query, length); DBUG_PRINT("query",("%-.4096s",thd->query)); #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.set_query_source(thd->query, length); @@ -1463,8 +1462,7 @@ int mysql_table_dump(THD* thd, char* db, if (check_one_table_access(thd, SELECT_ACL, table_list)) goto err; thd->free_list = 0; - thd->query_length=(uint) strlen(tbl_name); - thd->query = tbl_name; + thd->set_query(tbl_name, (uint) strlen(tbl_name)); if ((error = mysqld_dump_create_info(thd, table_list, -1))) { my_error(ER_GET_ERRNO, MYF(0), my_errno); @@ -1987,9 +1985,8 @@ bool dispatch_command(enum enum_server_c thd->profiling.set_query_source(next_packet, length); #endif + thd->set_query(next_packet, length); VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query_length= length; - thd->query= next_packet; /* Count each statement from the client. */ @@ -2041,9 +2038,10 @@ bool dispatch_command(enum enum_server_c table_list.schema_table= schema_table; } - thd->query_length= (uint) strlen(packet); // for simplicity: don't optimize - if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) + uint query_length= (uint) strlen(packet); + if (!(fields= thd->memdup(packet, query_length + 1))) break; + thd->set_query(fields, query_length); mysql_log.write(thd,command,"%s %s",table_list.table_name, fields); if (lower_case_table_names) my_casedn_str(files_charset_info, table_list.table_name); @@ -2327,13 +2325,12 @@ bool dispatch_command(enum enum_server_c log_slow_statement(thd); thd_proc_info(thd, "cleaning up"); - VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list - thd_proc_info(thd, 0); + thd->set_query(NULL, 0); thd->command=COM_SLEEP; - thd->query=0; - thd->query_length=0; + VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list thread_running--; VOID(pthread_mutex_unlock(&LOCK_thread_count)); + thd_proc_info(thd, 0); thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); DBUG_RETURN(error); @@ -2536,6 +2533,7 @@ int prepare_schema_table(THD *thd, LEX * bool alloc_query(THD *thd, const char *packet, uint packet_length) { + char *query; packet_length--; // Remove end null /* Remove garbage at start and end of query */ while (my_isspace(thd->charset(),packet[0]) && packet_length > 0) @@ -2551,14 +2549,13 @@ bool alloc_query(THD *thd, const char *p packet_length--; } /* We must allocate some extra memory for query cache */ - thd->query_length= 0; // Extra safety: Avoid races - if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet), - packet_length, - thd->db_length+ 1 + - QUERY_CACHE_FLAGS_SIZE))) - return TRUE; - thd->query[packet_length]=0; - thd->query_length= packet_length; + if (! (query= (char*) thd->memdup_w_gap(packet, + packet_length, + 1 + thd->db_length + + QUERY_CACHE_FLAGS_SIZE))) + return TRUE; + query[packet_length]= '\0'; + thd->set_query(query, packet_length); /* Reclaim some memory */ thd->packet.shrink(thd->variables.net_buffer_length); @@ -7506,7 +7503,7 @@ void kill_one_thread(THD *thd, ulong id, { if (tmp->thread_id == id) { - pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete + pthread_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete break; } } @@ -7539,7 +7536,7 @@ void kill_one_thread(THD *thd, ulong id, } else error=ER_KILL_DENIED_ERROR; - pthread_mutex_unlock(&tmp->LOCK_delete); + pthread_mutex_unlock(&tmp->LOCK_thd_data); } if (!error) === modified file 'sql/sql_repl.cc' --- a/sql/sql_repl.cc 2009-06-29 13:17:01 +0000 +++ b/sql/sql_repl.cc 2009-07-23 14:53:26 +0000 @@ -1044,7 +1044,7 @@ void kill_zombie_dump_threads(uint32 sla if (tmp->command == COM_BINLOG_DUMP && tmp->server_id == slave_server_id) { - pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete + pthread_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete break; } } @@ -1057,7 +1057,7 @@ void kill_zombie_dump_threads(uint32 sla again. We just to do kill the thread ourselves. */ tmp->awake(THD::KILL_QUERY); - pthread_mutex_unlock(&tmp->LOCK_delete); + pthread_mutex_unlock(&tmp->LOCK_thd_data); } } === modified file 'sql/sql_show.cc' --- a/sql/sql_show.cc 2009-07-16 12:37:38 +0000 +++ b/sql/sql_show.cc 2009-07-23 14:53:26 +0000 @@ -1410,16 +1410,14 @@ void mysqld_list_processes(THD *thd,cons thd_info->start_time= tmp->start_time; #endif thd_info->query=0; + /* Lock THD mutex that protects its data when looking at it. */ + pthread_mutex_lock(&tmp->LOCK_thd_data); if (tmp->query) { - /* - query_length is always set to 0 when we set query = NULL; see - the comment in sql_class.h why this prevents crashes in possible - races with query_length - */ uint length= min(max_query_length, tmp->query_length); thd_info->query=(char*) thd->strmake(tmp->query,length); } + pthread_mutex_unlock(&tmp->LOCK_thd_data); thread_infos.append(thd_info); } } --Boundary_(ID_3h9qRJt4TkS6zZiFiSZFYw) MIME-version: 1.0 Content-type: text/bzr-bundle; CHARSET=US-ASCII; name="bzr/gshchepa@stripped" Content-transfer-encoding: 7BIT Content-disposition: inline; filename="bzr/gshchepa@stripped" # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: gshchepa@stripped # target_branch: file:///home/uchum/work/bzr/38816-5.0/ # testament_sha1: c83cfce54c143a1e4264672abaef7cb50357ba8a # timestamp: 2009-07-23 19:53:35 +0500 # base_revision_id: epotemkin@stripped\ # q8547sn03h3qtfk8 # # Begin bundle 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 uSKcKEgyPlYhAA== --Boundary_(ID_3h9qRJt4TkS6zZiFiSZFYw)--