1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-40930: binlog-in-engine: seek() on invalid handle during change_user()

When using binlog-in-engine, the binlog trx cache is memory-only and does
not have an underlying temporary file backing the cache. The binlog code
must handle this and avoid calling into IO_CACHE code that manipulates the
underlying file. However, one case was forgotten where the binlog caches are
truncated during COM_CHANGE_USER / THD::change_user() (connection pool
reset), and the code would try to seek() on an invalid file handle. This
crashes on Windows and is just plain wrong on any platform.

Thanks to Vlad for analysis and test case.

Reviewed-by: Brandon Nesterenko <brandon.nesterenko@mariadb.com>
Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
Kristian Nielsen
2026-08-28 04:44:25 +02:00
parent fb216395ed
commit fd9d7c9c1c
4 changed files with 48 additions and 2 deletions

View File

@@ -0,0 +1,19 @@
#
# MDEV-40930: my_seek() on invalid file handle during COM_CHANGE_USER /
# COM_RESET_CONNECTION (connection pool reset) with
# binlog_storage_engine=innodb.
#
CREATE TABLE t1 (a INT, b VARCHAR(100)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1, 'x');
# COM_CHANGE_USER
change_user root,,test;
SELECT * FROM t1 ORDER BY a;
a b
1 x
INSERT INTO t1 VALUES (2, 'y');
# COM_RESET_CONNECTION -- dispatches to the same THD::change_user()
SELECT * FROM t1 ORDER BY a;
a b
1 x
2 y
DROP TABLE t1;

View File

@@ -0,0 +1,23 @@
--source include/have_binlog_format_row.inc
--source include/have_innodb_binlog.inc
--echo #
--echo # MDEV-40930: my_seek() on invalid file handle during COM_CHANGE_USER /
--echo # COM_RESET_CONNECTION (connection pool reset) with
--echo # binlog_storage_engine=innodb.
--echo #
CREATE TABLE t1 (a INT, b VARCHAR(100)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1, 'x');
--echo # COM_CHANGE_USER
--change_user root,,test
SELECT * FROM t1 ORDER BY a;
INSERT INTO t1 VALUES (2, 'y');
--echo # COM_RESET_CONNECTION -- dispatches to the same THD::change_user()
reset_connection;
SELECT * FROM t1 ORDER BY a;
DROP TABLE t1;

View File

@@ -123,6 +123,7 @@ static void reset_tracking_io_cache(IO_CACHE *info)
void truncate_io_cache(IO_CACHE *info)
{
DBUG_ASSERT(info->file >= (File)0);
if (mysql_file_seek(info->file, 0L, MY_SEEK_END, MYF(0)) != 0 &&
my_chsize(info->file, 0, 0, MYF(MY_WME)) == 0)
reset_tracking_io_cache(info);

View File

@@ -580,8 +580,11 @@ public:
/* Truncate temporary files if needed. Used with change_user */
void truncate_tmp_files()
{
stmt_cache.truncate_cache_file();
trx_cache.truncate_cache_file();
if (!opt_binlog_engine_hton)
{
stmt_cache.truncate_cache_file();
trx_cache.truncate_cache_file();
}
}
binlog_cache_data* get_binlog_cache_data(bool is_transactional)