diff --git a/mysql-test/r/mdl_sync.result b/mysql-test/r/mdl_sync.result index 984f0df3d0e..8f236521f99 100644 --- a/mysql-test/r/mdl_sync.result +++ b/mysql-test/r/mdl_sync.result @@ -2381,3 +2381,17 @@ commit; # Reap ALTER TABLE. set debug_sync= 'RESET'; drop table t1; +# +# Bug#52856 concurrent show columns or show full columns causes a crash!!! +# +CREATE TABLE t1(a CHAR(255)); +SET DEBUG_SYNC= "get_schema_column SIGNAL waiting WAIT_FOR completed"; +SHOW FULL COLUMNS FROM t1; +SET DEBUG_SYNC= "now WAIT_FOR waiting"; +SHOW FULL COLUMNS FROM t1; +Field Type Collation Null Key Default Extra Privileges Comment +a char(255) latin1_swedish_ci YES NULL select,insert,update,references +SET DEBUG_SYNC= "now SIGNAL completed"; +Field Type Collation Null Key Default Extra Privileges Comment +a char(255) latin1_swedish_ci YES NULL select,insert,update,references +DROP TABLE t1; diff --git a/mysql-test/t/mdl_sync.test b/mysql-test/t/mdl_sync.test index ef434e33cfa..dff29d2f6b6 100644 --- a/mysql-test/t/mdl_sync.test +++ b/mysql-test/t/mdl_sync.test @@ -3468,6 +3468,26 @@ connection default; set debug_sync= 'RESET'; drop table t1; +--echo # +--echo # Bug#52856 concurrent show columns or show full columns causes a crash!!! +--echo # +CREATE TABLE t1(a CHAR(255)); + +connect(con1, localhost, root); +SET DEBUG_SYNC= "get_schema_column SIGNAL waiting WAIT_FOR completed"; +--send SHOW FULL COLUMNS FROM t1 + +connection default; +SET DEBUG_SYNC= "now WAIT_FOR waiting"; +SHOW FULL COLUMNS FROM t1; +SET DEBUG_SYNC= "now SIGNAL completed"; + +connection con1; +--reap +connection default; +DROP TABLE t1; +disconnect con1; + # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 00a507f0e47..07470ff4f42 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -18,6 +18,7 @@ #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" +#include "debug_sync.h" #include "unireg.h" #include "sql_acl.h" // fill_schema_*_privileges #include "sql_select.h" // For select_describe @@ -3292,12 +3293,17 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables, goto end_share; } + if (!open_table_from_share(thd, share, table_name->str, 0, + (EXTRA_RECORD | OPEN_FRM_FILE_ONLY), + thd->open_options, &tbl, FALSE)) { tbl.s= share; table_list.table= &tbl; table_list.view= (LEX*) share->is_view; res= schema_table->process_table(thd, &table_list, table, res, db_name, table_name); + free_root(&tbl.mem_root, MYF(0)); + my_free((char*) tbl.alias, MYF(MY_ALLOW_ZERO_PTR)); } end_share: @@ -4024,7 +4030,6 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, const char *wild= lex->wild ? lex->wild->ptr() : NullS; CHARSET_INFO *cs= system_charset_info; TABLE *show_table; - TABLE_SHARE *show_table_share; Field **ptr, *field, *timestamp_field; int count; DBUG_ENTER("get_schema_column_record"); @@ -4047,37 +4052,11 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, } show_table= tables->table; - show_table_share= show_table->s; count= 0; - - if (tables->view || tables->schema_table) - { - ptr= show_table->field; - timestamp_field= show_table->timestamp_field; - show_table->use_all_columns(); // Required for default - } - else - { - ptr= show_table_share->field; - timestamp_field= show_table_share->timestamp_field; - /* - read_set may be inited in case of - temporary table - */ - if (!show_table->read_set) - { - /* to satisfy 'field->val_str' ASSERTs */ - uchar *bitmaps; - uint bitmap_size= show_table_share->column_bitmap_size; - if (!(bitmaps= (uchar*) alloc_root(thd->mem_root, bitmap_size))) - DBUG_RETURN(0); - bitmap_init(&show_table->def_read_set, - (my_bitmap_map*) bitmaps, show_table_share->fields, FALSE); - bitmap_set_all(&show_table->def_read_set); - show_table->read_set= &show_table->def_read_set; - } - bitmap_set_all(show_table->read_set); - } + ptr= show_table->field; + timestamp_field= show_table->timestamp_field; + show_table->use_all_columns(); // Required for default + restore_record(show_table, s->default_values); for (; (field= *ptr) ; ptr++) { @@ -4086,9 +4065,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, String type(tmp,sizeof(tmp), system_charset_info); char *end; - /* to satisfy 'field->val_str' ASSERTs */ - field->table= show_table; - show_table->in_use= thd; + DEBUG_SYNC(thd, "get_schema_column"); if (wild && wild[0] && wild_case_compare(system_charset_info, field->field_name,wild))