Commit 84c205f9 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.)
parent b4c213c8
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, ...@@ -291,7 +291,8 @@ uint explain_filename(THD* thd,
{ {
if (explain_mode == EXPLAIN_ALL_VERBOSE) 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++)= ' ';
to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len); to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len);
to_p= strnmov(to_p, ", ", end_p - to_p); to_p= strnmov(to_p, ", ", end_p - to_p);
...@@ -304,7 +305,7 @@ uint explain_filename(THD* thd, ...@@ -304,7 +305,7 @@ uint explain_filename(THD* thd,
} }
if (explain_mode == EXPLAIN_ALL_VERBOSE) 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++)= ' ';
to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len); to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len);
} }
...@@ -321,18 +322,22 @@ uint explain_filename(THD* thd, ...@@ -321,18 +322,22 @@ uint explain_filename(THD* thd,
if (name_type != NORMAL) if (name_type != NORMAL)
{ {
if (name_type == TEMP) 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 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, " ", 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++)= ' ';
to_p= add_identifier(thd, to_p, end_p, part_name, part_name_len); to_p= add_identifier(thd, to_p, end_p, part_name, part_name_len);
if (subpart_name) if (subpart_name)
{ {
to_p= strnmov(to_p, ", ", end_p - to_p); 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++)= ' ';
to_p= add_identifier(thd, to_p, end_p, subpart_name, subpart_name_len); to_p= add_identifier(thd, to_p, end_p, subpart_name, subpart_name_len);
} }
......
...@@ -46,6 +46,9 @@ ...@@ -46,6 +46,9 @@
#define ER(X) CURRENT_THD_ERRMSGS[(X) - ER_ERROR_FIRST] #define ER(X) CURRENT_THD_ERRMSGS[(X) - ER_ERROR_FIRST]
#define ER_DEFAULT(X) DEFAULT_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_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 */ #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