From bc87dfe251a3909279f71b1061412d8d159bb942 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Wed, 17 Feb 2010 18:07:28 +0000 Subject: BUG#48993: valgrind errors in mysqlbinlog I found three issues during the analysis: 1. Memory leak caused by temp_buf not being freed; 2. Memory leak caused when handling argv; 3. Conditional jump that depended on unitialized values. Issue #1 -------- DESCRIPTION: when mysqlbinlog is reading from a remote location the event temp_buf references the incoming stream (in NET object), which is not freed by mysqlbinlog explicitly. On the other hand, when it is reading local binary log, it points to a temporary buffer that needs to be explicitly freed. For both cases, the temp_buf was not freed by mysqlbinlog, instead was set to 0. This clearly disregards the free required in the second case, thence creating a memory leak. FIX: we make temp_buf to be conditionally freed depending on the value of remote_opt. Found out that similar fix is already in most recent codebases. Issue #2 -------- DESCRIPTION: load_defaults is called by parse_args, and it reads default options from configuration files and put them BEFORE the arguments that are already in argc and argv. This is done resorting to MEM_ROOT. However, parse_args calls handle_options immediately after which changes argv. Later when freeing the defaults, pointers to MEM_ROOT won't match, causing the memory not to be freed: void free_defaults(char **argv) { MEM_ROOT ptr memcpy_fixed((char*) &ptr,(char *) argv - sizeof(ptr), sizeof(ptr)); free_root(&ptr,MYF(0)); } FIX: we remove load_defaults from parse_args and call it before. Then we save argv with defaults in defaults_argv BEFORE calling parse_args (which inside can then call handle_options at will). Actually, found out that this is in fact kind of a backport for BUG#38468 into 5.1, so I merged in the test case as well and added error check for load_defaults call. Fix based on: revid:zhenxing.he@sun.com-20091002081840-uv26f0flw4uvo33y Issue #3 -------- DESCRIPTION: the structure st_print_event_info constructor would not initialize the sql_mode member, although it did for sql_mode_inited (set to false). This would later raise the warning in valgrind when printing the sql_mode in the event header, as this print out is protected by a check against sql_mode_inited and sql_mode variables. Given that sql_mode was not initialized valgrind would output the warning. FIX: we add initialization of sql_mode to the st_print_event_info constructor. client/mysqlbinlog.cc: - Conditionally free ev->temp_buf. - save defaults_argv before handle_options is called. mysql-test/t/mysqlbinlog.test: Added test case from BUG#38468. sql/log_event.cc: Added initialization of sql_mode for st_print_event_info. --- mysql-test/t/mysqlbinlog.test | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'mysql-test/t/mysqlbinlog.test') diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 687ad62b17c..0d3f0a8a7c4 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -443,3 +443,27 @@ FLUSH LOGS; --echo End of 5.0 tests --echo End of 5.1 tests + +# +# BUG#38468 Memory leak detected when using mysqlbinlog utility; +# +disable_query_log; +RESET MASTER; +CREATE TABLE t1 SELECT 1; +FLUSH LOGS; +DROP TABLE t1; +enable_query_log; + +# Write an empty file for comparison +write_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn.empty; +EOF + +# Before fix of BUG#38468, this would generate some warnings +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 >/dev/null 2> $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn + +# Make sure the command above does not generate any error or warnings +diff_files $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn.empty; + +# Cleanup for this part of test +remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn.empty; +remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn; -- cgit v1.2.1 From 78557dd4636f470287bad95f200b63ed566f6085 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 Mar 2010 19:57:33 +0800 Subject: Bug #50407 mysqlbinlog --database=X produces bad output for SAVEPOINTs When mysqlbinlog was given the --database=X flag, it always printed 'ROLLBACK TO', but the corresponding 'SAVEPOINT' statement was not printed. The replicated filter(replicated-do/ignore-db) and binlog filter (binlog-do/ignore-db) has the same problem. They are solved in this patch together. After this patch, We always check whether the query is 'SAVEPOINT' statement or not. Because this is a literal check, 'SAVEPOINT' and 'ROLLBACK TO' statements are also binlogged in uppercase with no any comments. The binlog before this patch can be handled correctly except one case that any comments are in front of the keywords. for example: /* bla bla */ SAVEPOINT a; /* bla bla */ ROLLBACK TO a; --- mysql-test/t/mysqlbinlog.test | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'mysql-test/t/mysqlbinlog.test') diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 0d3f0a8a7c4..7c9fbf031bb 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -434,12 +434,19 @@ FLUSH LOGS; # Transaction3 end --echo # ---echo # Test if the 'BEGIN', 'ROLLBACK' and 'COMMIT' are output if the database specified is exist +--echo # Test if the 'BEGIN', 'ROLLBACK' and 'COMMIT' are output if the database specified exists --exec $MYSQL_BINLOG --database=test --short-form $MYSQLTEST_VARDIR/std_data/binlog_transaction.000001 --echo # ---echo # Test if the 'BEGIN', 'ROLLBACK' and 'COMMIT' are output if the database specified is not exist +--echo # Test if the 'BEGIN', 'ROLLBACK' and 'COMMIT' are output if the database specified does not exist --exec $MYSQL_BINLOG --database=not_exist --short-form $MYSQLTEST_VARDIR/std_data/binlog_transaction.000001 +--echo # +--echo # Test if the 'SAVEPOINT', 'ROLLBACK TO' are output if the database specified exists +--exec $MYSQL_BINLOG --database=db1 --short-form $MYSQLTEST_VARDIR/std_data/binlog_savepoint.000001 +--echo # +--echo # Test if the 'SAVEPOINT', 'ROLLBACK TO' are output if the database specified does not exist +--exec $MYSQL_BINLOG --database=not_exist --short-form $MYSQLTEST_VARDIR/std_data/binlog_savepoint.000001 + --echo End of 5.0 tests --echo End of 5.1 tests -- cgit v1.2.1