[MDEV-14410] Assertion `table->pos_in_locked_tables == __null || table->pos_in_locked_tables->table == table' failed in mark_used_tables_as_free_for_reuse Created: 2017-11-15  Updated: 2019-01-23  Resolved: 2018-09-18

Status: Closed
Project: MariaDB Server
Component/s: Locking
Affects Version/s: 10.0, 10.1, 10.2, 10.3
Fix Version/s: 10.0.37, 10.2.18, 10.3.10, 10.1.37

Type: Bug Priority: Critical
Reporter: Elena Stepanova Assignee: Sergei Golubchik
Resolution: Fixed Votes: 0
Labels: affects-tests

Issue Links:
Relates
relates to MDEV-17275 Assertion `thd->mdl_context.is_lock_o... Closed
relates to MDEV-18154 Deadlock and assertion upon no-op ALT... Closed

 Description   

--source include/have_innodb.inc
 
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (b INT);
 
CREATE TABLE t3 (c INT);
CREATE TABLE t4 (d INT);
CREATE TABLE t5 (e INT);
 
CREATE TRIGGER tr1 BEFORE INSERT ON t2 FOR EACH ROW INSERT INTO t4 VALUES ();
CREATE TRIGGER tr2 BEFORE INSERT ON t3 FOR EACH ROW INSERT INTO t1 VALUES ();
CREATE TRIGGER tr3 BEFORE INSERT ON t4 FOR EACH ROW INSERT INTO t3 SELECT * FROM t1;
CREATE TRIGGER tr4 BEFORE INSERT ON t5 FOR EACH ROW INSERT INTO t4 VALUES ();
 
--connect (con1,localhost,root,,test)
LOCK TABLE t1 WRITE, t4 WRITE;
 
--connection default
--send
	INSERT INTO t2 VALUES (1);
 
--connection con1
CREATE OR REPLACE TABLE t1 (i INT);
UNLOCK TABLES;
 
--connection default
--reap
 
# Cleanup
--disconnect con1
--connection default
DROP TABLE t1, t2, t3, t4, t5;

10.0 d8ccc61f76d5

Version: '10.0.34-MariaDB-debug'  socket: '/data/bld/10.0/mysql-test/var/tmp/mysqld.1.sock'  port: 16000  Source distribution
mysqld: /data/src/10.0/sql/sql_base.cc:746: void mark_used_tables_as_free_for_reuse(THD*, TABLE*): Assertion `table->pos_in_locked_tables == __null || table->pos_in_locked_tables->table == table' failed.
171123 13:47:23 [ERROR] mysqld got signal 6 ;
 
#7  0x00007f2facbadee2 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
#8  0x00000000005e88d0 in mark_used_tables_as_free_for_reuse (thd=0x7f2fa0f69070, table=0x7f2f98c88870) at /data/src/10.0/sql/sql_base.cc:745
#11 0x000000000097c6dc in sp_instr_stmt::exec_core (this=0x7f2f98cd0d88, thd=0x7f2fa0f69070, nextp=0x7f2faec712d8) at /data/src/10.0/sql/sp_head.cc:3210
#12 0x000000000097bdeb in sp_lex_keeper::reset_lex_and_exec_core (this=0x7f2f98cd0dc8, thd=0x7f2fa0f69070, nextp=0x7f2faec712d8, open_tables=false, instr=0x7f2f98cd0d88) at /data/src/10.0/sql/sp_head.cc:2977
#13 0x000000000097c3a6 in sp_instr_stmt::execute (this=0x7f2f98cd0d88, thd=0x7f2fa0f69070, nextp=0x7f2faec712d8) at /data/src/10.0/sql/sp_head.cc:3126
#14 0x0000000000978177 in sp_head::execute (this=0x7f2f98ccd088, thd=0x7f2fa0f69070, merge_da_on_success=false) at /data/src/10.0/sql/sp_head.cc:1369
#15 0x0000000000978c31 in sp_head::execute_trigger (this=0x7f2f98ccd088, thd=0x7f2fa0f69070, db_name=0x7f2f98c351d8, table_name=0x7f2f98c351e8, grant_info=0x7f2f98cb9138) at /data/src/10.0/sql/sp_head.cc:1697
#16 0x000000000070eb58 in Table_triggers_list::process_triggers (this=0x7f2f98cb9088, thd=0x7f2fa0f69070, event=TRG_EVENT_INSERT, time_type=TRG_ACTION_BEFORE, old_row_is_record1=true) at /data/src/10.0/sql/sql_trigger.cc:2103
#17 0x00000000005f84c2 in fill_record_n_invoke_before_triggers (thd=0x7f2fa0f69070, table=0x7f2f98c88870, fields=..., values=..., ignore_errors=false, event=TRG_EVENT_INSERT) at /data/src/10.0/sql/sql_base.cc:8766
#18 0x000000000062e6c8 in mysql_insert (thd=0x7f2fa0f69070, table_list=0x7f2f98a03088, fields=..., values_list=..., update_fields=..., update_values=..., duplic=DUP_ERROR, ignore=false) at /data/src/10.0/sql/sql_insert.cc:880
#19 0x000000000064e89f in mysql_execute_command (thd=0x7f2fa0f69070) at /data/src/10.0/sql/sql_parse.cc:3449
#20 0x000000000097c6dc in sp_instr_stmt::exec_core (this=0x7f2f98a03668, thd=0x7f2fa0f69070, nextp=0x7f2faec72628) at /data/src/10.0/sql/sp_head.cc:3210
#21 0x000000000097bdeb in sp_lex_keeper::reset_lex_and_exec_core (this=0x7f2f98a036a8, thd=0x7f2fa0f69070, nextp=0x7f2faec72628, open_tables=false, instr=0x7f2f98a03668) at /data/src/10.0/sql/sp_head.cc:2977
#22 0x000000000097c3a6 in sp_instr_stmt::execute (this=0x7f2f98a03668, thd=0x7f2fa0f69070, nextp=0x7f2faec72628) at /data/src/10.0/sql/sp_head.cc:3126
#23 0x0000000000978177 in sp_head::execute (this=0x7f2f98a00088, thd=0x7f2fa0f69070, merge_da_on_success=false) at /data/src/10.0/sql/sp_head.cc:1369
#24 0x0000000000978c31 in sp_head::execute_trigger (this=0x7f2f98a00088, thd=0x7f2fa0f69070, db_name=0x7f2f98860fd8, table_name=0x7f2f98860fe8, grant_info=0x7f2f98952338) at /data/src/10.0/sql/sp_head.cc:1697
#25 0x000000000070eb58 in Table_triggers_list::process_triggers (this=0x7f2f98952288, thd=0x7f2fa0f69070, event=TRG_EVENT_INSERT, time_type=TRG_ACTION_BEFORE, old_row_is_record1=true) at /data/src/10.0/sql/sql_trigger.cc:2103
#26 0x00000000005f8a21 in fill_record_n_invoke_before_triggers (thd=0x7f2fa0f69070, table=0x7f2f9889e470, ptr=0x7f2f98828998, values=..., ignore_errors=false, event=TRG_EVENT_INSERT) at /data/src/10.0/sql/sql_base.cc:8910
#27 0x000000000062e818 in mysql_insert (thd=0x7f2fa0f69070, table_list=0x7f2f989a4168, fields=..., values_list=..., update_fields=..., update_values=..., duplic=DUP_ERROR, ignore=false) at /data/src/10.0/sql/sql_insert.cc:924
#28 0x000000000064e89f in mysql_execute_command (thd=0x7f2fa0f69070) at /data/src/10.0/sql/sql_parse.cc:3449
#29 0x0000000000656dc2 in mysql_parse (thd=0x7f2fa0f69070, rawbuf=0x7f2f989a4088 "INSERT INTO t2 VALUES (1)", length=25, parser_state=0x7f2faec73640) at /data/src/10.0/sql/sql_parse.cc:6569
#30 0x0000000000649901 in dispatch_command (command=COM_QUERY, thd=0x7f2fa0f69070, packet=0x7f2fa69ef071 "INSERT INTO t2 VALUES (1)", packet_length=25) at /data/src/10.0/sql/sql_parse.cc:1296
#31 0x0000000000648c01 in do_command (thd=0x7f2fa0f69070) at /data/src/10.0/sql/sql_parse.cc:999
#32 0x0000000000768ab8 in do_handle_one_connection (thd_arg=0x7f2fa0f69070) at /data/src/10.0/sql/sql_connect.cc:1377
#33 0x000000000076882a in handle_one_connection (arg=0x7f2fa0f69070) at /data/src/10.0/sql/sql_connect.cc:1292
#34 0x0000000000ac9564 in pfs_spawn_thread (arg=0x7f2fa0f19670) at /data/src/10.0/storage/perfschema/pfs.cc:1861
#35 0x00007f2fae8b1494 in start_thread (arg=0x7f2faec74700) at pthread_create.c:333
#36 0x00007f2facc6a93f in clone () from /lib/x86_64-linux-gnu/libc.so.6

Reproducible on 10.0 - 10.3 with MyISAM, InnoDB, Aria. Not applicable to 5.5 or MySQL because of CREATE OR REPLACE.



 Comments   
Comment by Elena Stepanova [ 2018-07-24 ]

Still reproducible on current bulds (at least 10.0 ada54101a71, 10.3 141a5b2484).

Comment by Sergey Vojtovich [ 2018-09-06 ]

Simplified test case:

CREATE TABLE t1 (a INT);
CREATE TABLE t2 (b INT);
CREATE TABLE t3 (c INT);
 
CREATE TRIGGER tr1 BEFORE INSERT ON t3 FOR EACH ROW INSERT INTO t1 VALUES ();
CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW INSERT INTO t3 SELECT * FROM t1;
 
LOCK TABLE t1 WRITE, t2 WRITE;
CREATE OR REPLACE TABLE t1 (i INT);
UNLOCK TABLES;
INSERT INTO t2 VALUES (1);
 
# Cleanup
DROP TABLE t1, t2, t3;

Comment by Sergey Vojtovich [ 2018-09-06 ]

Apparently it was broken in 2012 by b1485a4780808cd95cbc37c1f59024b39d542584, specifically this hunk:

@@ -1412,10 +1415,13 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
     {
       thd->locked_tables_list.unlink_from_list(thd,
                                                table->pos_in_locked_tables,
-                                               extra != HA_EXTRA_NORMAL);
-      /* Inform handler that there is a drop table or rename going on */
-      if (extra != HA_EXTRA_NORMAL && table->db_stat)
+                                               extra != HA_EXTRA_NOT_USED);
+      /* Inform handler that there is a drop table or a rename going on */
+      if (extra != HA_EXTRA_NOT_USED && table->db_stat)
+      {
         table->file->extra(extra);
+        extra= HA_EXTRA_NOT_USED;               // Call extra once!
+      }
 
       /*
         Does nothing if the table is not locked.

In other words it would remove only first instance of a table from m_locked_tables list (previously removed all) due to "extra= HA_EXTRA_NOT_USED" reset. This eventually breaks m_locked_tables list when still-in-the-list instance is added back to the list again using thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);

Comment by Sergey Vojtovich [ 2018-09-07 ]

serg, please review fix for this bug.
https://github.com/mariadb/server/commit/01bd1917e458f7c1bd52584b3ff15c968ed9034d

Comment by Sergei Golubchik [ 2018-09-18 ]

ok to push!

Generated at Thu Feb 08 08:13:19 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.