Commit dca67006 authored by Mattias Jonsson's avatar Mattias Jonsson

Bug#50201: Server crashes in explain_filename on an InnoDB partitioned table

Problem was that in mysql-trunk the ER() macro is now dependent on current_thd
and the innodb monitor thread has no binding to that thd object. This cause 
the crash because of bad derefencing.

Solution was to add a new macro which take the thd as an argument (which the innodb
thread uses for the call).

(Updated according to reviewers comments, i.e. added ER_THD_OR_DEFAULT and
moved test to suite parts.)

mysql-test/suite/parts/r/partition_innodb_status_file.result:
  Bug#50201: Server crashes in explain_filename on an InnoDB partitioned table
  
  New test result file
mysql-test/suite/parts/t/partition_innodb_status_file-master.opt:
  Bug#50201: Server crashes in explain_filename on an InnoDB partitioned table
  
  New test opt file
mysql-test/suite/parts/t/partition_innodb_status_file.test:
  Bug#50201: Server crashes in explain_filename on an InnoDB partitioned table
  
  New test.
  Note that the innodb monitor thread only runs every 15 seconds, so this
  test will take at least 15 seconds, so I have moved it to the parts suite.
sql/sql_table.cc:
  Bug#50201: Server crashes in explain_filename on an InnoDB partitioned table
  
  Using thd safe ER macro.
sql/unireg.h:
  Bug#50201: Server crashes in explain_filename on an InnoDB partitioned table
  
  Added ER macros for use with specified thd pointer.
parent f5311bba
CREATE TABLE t1 (a INT) ENGINE = InnoDB PARTITION BY HASH(a);
INSERT INTO t1 VALUES (0), (1), (2);
START TRANSACTION;
UPDATE t1 SET a = 5 WHERE a = 1;
# Connection con1
# InnoDB lock timeout and monitor thread runs every 15 seconds
SET innodb_lock_wait_timeout = 20;
START TRANSACTION;
UPDATE t1 SET a = 3 WHERE a = 1;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
COMMIT;
# Connection default
COMMIT;
DROP TABLE t1;
--source include/have_innodb.inc
--source include/have_partition.inc
CREATE TABLE t1 (a INT) ENGINE = InnoDB PARTITION BY HASH(a);
INSERT INTO t1 VALUES (0), (1), (2);
START TRANSACTION;
UPDATE t1 SET a = 5 WHERE a = 1;
connect (con1, localhost, root,,);
--echo # Connection con1
--echo # InnoDB lock timeout and monitor thread runs every 15 seconds
SET innodb_lock_wait_timeout = 20;
START TRANSACTION;
--error ER_LOCK_WAIT_TIMEOUT
UPDATE t1 SET a = 3 WHERE a = 1;
COMMIT;
disconnect con1;
connection default;
--echo # Connection default
COMMIT;
DROP TABLE t1;
......@@ -291,7 +291,8 @@ uint explain_filename(THD* thd,
{
if (explain_mode == EXPLAIN_ALL_VERBOSE)
{
to_p= strnmov(to_p, ER(ER_DATABASE_NAME), end_p - to_p);
to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_DATABASE_NAME),
end_p - to_p);
*(to_p++)= ' ';
to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len);
to_p= strnmov(to_p, ", ", end_p - to_p);
......@@ -304,7 +305,7 @@ uint explain_filename(THD* thd,
}
if (explain_mode == EXPLAIN_ALL_VERBOSE)
{
to_p= strnmov(to_p, ER(ER_TABLE_NAME), end_p - to_p);
to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_TABLE_NAME), end_p - to_p);
*(to_p++)= ' ';
to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len);
}
......@@ -321,18 +322,22 @@ uint explain_filename(THD* thd,
if (name_type != NORMAL)
{
if (name_type == TEMP)
to_p= strnmov(to_p, ER(ER_TEMPORARY_NAME), end_p - to_p);
to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_TEMPORARY_NAME),
end_p - to_p);
else
to_p= strnmov(to_p, ER(ER_RENAMED_NAME), end_p - to_p);
to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_RENAMED_NAME),
end_p - to_p);
to_p= strnmov(to_p, " ", end_p - to_p);
}
to_p= strnmov(to_p, ER(ER_PARTITION_NAME), end_p - to_p);
to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_PARTITION_NAME),
end_p - to_p);
*(to_p++)= ' ';
to_p= add_identifier(thd, to_p, end_p, part_name, part_name_len);
if (subpart_name)
{
to_p= strnmov(to_p, ", ", end_p - to_p);
to_p= strnmov(to_p, ER(ER_SUBPARTITION_NAME), end_p - to_p);
to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_SUBPARTITION_NAME),
end_p - to_p);
*(to_p++)= ' ';
to_p= add_identifier(thd, to_p, end_p, subpart_name, subpart_name_len);
}
......
......@@ -46,6 +46,9 @@
#define ER(X) CURRENT_THD_ERRMSGS[(X) - ER_ERROR_FIRST]
#define ER_DEFAULT(X) DEFAULT_ERRMSGS[(X) - ER_ERROR_FIRST]
#define ER_SAFE(X) (((X) >= ER_ERROR_FIRST && (X) <= ER_ERROR_LAST) ? ER(X) : "Invalid error code")
#define ER_THD(thd,X) ((thd)->variables.lc_messages->errmsgs->errmsgs[(X) - \
ER_ERROR_FIRST])
#define ER_THD_OR_DEFAULT(thd,X) ((thd) ? ER_THD(thd, X) : ER_DEFAULT(X))
#define ERRMAPP 1 /* Errormap f|r my_error */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment