List:Commits« Previous MessageNext Message »
From:He Zhenxing Date:March 19 2009 6:31am
Subject:Re: bzr commit into mysql-5.1-bugteam branch (alfranio.correia:2832)
Bug#42861
View as plain text  
Hi Alfranio,

Nice work, patch approved!

Alfranio Correia wrote:
> #At
> file:///home/acorreia/workspace.sun/repository.mysql/bzrwork/bug-42861/mysql-5.1-bugteam/
> based on revid:joro@stripped
> 
>  2832 Alfranio Correia	2009-03-18
>       Bug #42861 Assigning invalid directories to --slave-load-tmpdir crashes the
> slave
>       
>       Compiling with debug and assigning an invalid directory to --slave-load-tmpdir
>       was crashing the slave due to the following assertion DBUG_ASSERT(! is_set()
> ||
>       can_overwrite_status). This assertion assumes that a thread can change its
>       state once (i.e. ok,error, etc) before aborting, cleaning/resuming or
> completing
>       its execution unless the overwrite flag (i.e. can_overwrite_status) is true.
>       
>       The Append_block_log_event::do_apply_event which is responsible for creating
>       temporary file(s) was not cleaning the thread state. Thus a failure while
>       trying to create a file in an invalid temporary directory was causing the
> crash.
>       
>       To fix the problem we check if the temporary directory is valid before
> starting
>       the SQL Thread and reset the thread state before creating a file in
>       Append_block_log_event::do_apply_event.
> added:
>   mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result
>   mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result
>   mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile-slave.opt
>   mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test
>   mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt
>   mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test
> modified:
>   mysql-test/suite/rpl/r/rpl_slave_load_in.result
>   mysql-test/suite/rpl/t/rpl_slave_load_in.test
>   sql/log_event.cc
>   sql/slave.cc
> 
> === modified file 'mysql-test/suite/rpl/r/rpl_slave_load_in.result'
> --- a/mysql-test/suite/rpl/r/rpl_slave_load_in.result	2009-02-21 09:36:07 +0000
> +++ b/mysql-test/suite/rpl/r/rpl_slave_load_in.result	2009-03-18 10:31:17 +0000
> @@ -5,6 +5,15 @@ reset slave;
>  drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
>  start slave;
>  create table t1(a int not null auto_increment, b int, primary key(a));
> +create table t2(a int not null auto_increment, b int, primary key(a))
> engine=innodb;
>  load data infile '../../std_data/rpl_loaddata.dat' into table t1;
> +start transaction;
> +insert into t2(b) values (1);
> +insert into t2(b) values (2);
> +load data infile '../../std_data/rpl_loaddata.dat' into table t2;
> +load data infile '../../std_data/rpl_loaddata.dat' into table t2;
> +commit;
>  Comparing tables master:test.t1 and slave:test.t1
> +Comparing tables master:test.t2 and slave:test.t2
>  drop table t1;
> +drop table t2;
> 
> === added file 'mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result'
> --- a/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result	1970-01-01 00:00:00
> +0000
> +++ b/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result	2009-03-18 10:31:17
> +0000
> @@ -0,0 +1,15 @@
> +stop slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +reset master;
> +reset slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +start slave;
> +create table t1(a int not null auto_increment, b int, primary key(a))
> engine=innodb;
> +start transaction;
> +insert into t1(b) values (1);
> +insert into t1(b) values (2);
> +load data infile '../../std_data/rpl_loaddata.dat' into table t1;
> +commit;
> +Error in Begin_load_query event: write to '../../tmp/SQL_LOAD-2-1-1.data' failed
> +drop table t1;
> +drop table t1;
> 
> === added file 'mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result'
> --- a/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result	1970-01-01
> 00:00:00 +0000
> +++ b/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result	2009-03-18
> 10:31:17 +0000
> @@ -0,0 +1,2 @@
> +start slave;
> +Unable to use slave's temporary directory ../../../error - Can't read dir of
> '../../../error' (Errcode: 2)
> 
> === modified file 'mysql-test/suite/rpl/t/rpl_slave_load_in.test'
> --- a/mysql-test/suite/rpl/t/rpl_slave_load_in.test	2009-02-21 09:36:07 +0000
> +++ b/mysql-test/suite/rpl/t/rpl_slave_load_in.test	2009-03-18 10:31:17 +0000
> @@ -3,10 +3,11 @@
>  # event while the "--secure-file-priv" option is set.
>  # 
>  # The test is divided in two steps:
> -#    1 - Creates a table and populates it through "LOAD DATA INFILE".
> +#    1 - Creates tables and populates them through "LOAD DATA INFILE".
>  #    2 - Compares the master and slave.
>  ##########################################################################
> -source include/master-slave.inc;
> +--source include/have_innodb.inc
> +--source include/master-slave.inc
>  
>  ##########################################################################
>  #                            Loading data
> @@ -14,8 +15,17 @@ source include/master-slave.inc;
>  connection master;
>  
>  create table t1(a int not null auto_increment, b int, primary key(a));
> +create table t2(a int not null auto_increment, b int, primary key(a))
> engine=innodb;
> +
>  load data infile '../../std_data/rpl_loaddata.dat' into table t1;
>  
> +start transaction;
> +  insert into t2(b) values (1);
> +  insert into t2(b) values (2);
> +  load data infile '../../std_data/rpl_loaddata.dat' into table t2;
> +  load data infile '../../std_data/rpl_loaddata.dat' into table t2;
> +commit;
> +
>  ##########################################################################
>  #                       Checking Consistency
>  ##########################################################################
> @@ -25,11 +35,16 @@ let $diff_table_1=master:test.t1;
>  let $diff_table_2=slave:test.t1;
>  source include/diff_tables.inc;
>  
> +let $diff_table_1=master:test.t2;
> +let $diff_table_2=slave:test.t2;
> +source include/diff_tables.inc;
> +
>  ##########################################################################
>  #                             Clean up
>  ##########################################################################
>  connection master;
>  
>  drop table t1;
> +drop table t2;
>  
>  sync_slave_with_master;
> 
> === added file 'mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile-slave.opt'
> --- a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile-slave.opt	1970-01-01
> 00:00:00 +0000
> +++ b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile-slave.opt	2009-03-18
> 10:31:17 +0000
> @@ -0,0 +1 @@
> +--loose-debug=d,remove_slave_load_file_before_write
> 
> === added file 'mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test'
> --- a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test	1970-01-01 00:00:00
> +0000
> +++ b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test	2009-03-18 10:31:17
> +0000
> @@ -0,0 +1,46 @@
> +##########################################################################
> +# This test verifies if the slave fails gracefully when the temporary 
> +# file used to load data is removed while it is about to be used it. 
> +# Similar errors are caught if the temporary directory is removed.
> +#
> +# Steps:
> +#    1 - Creates a table and populates it through "LOAD DATA INFILE".
> +#    2 - Catches error.
> +##########################################################################
> +--source include/have_binlog_format_mixed_or_statement.inc
> +--source include/have_innodb.inc
> +--source include/have_debug.inc
> +--source include/master-slave.inc
> +
> +##########################################################################
> +#                            Loading data
> +##########################################################################
> +connection master;
> +
> +create table t1(a int not null auto_increment, b int, primary key(a))
> engine=innodb;
> +
> +start transaction;
> +  insert into t1(b) values (1);
> +  insert into t1(b) values (2);
> +  load data infile '../../std_data/rpl_loaddata.dat' into table t1;
> +commit;
> +
> +##########################################################################
> +#                            Catch Error
> +##########################################################################
> +connection slave;
> +source include/wait_for_slave_sql_to_stop.inc;
> +
> +let $error=query_get_value("show slave status", Last_SQL_Error, 1);
> +echo $error;
> +
> +##########################################################################
> +#                             Clean up
> +##########################################################################
> +connection master;
> +
> +drop table t1;
> +
> +connection slave;
> +
> +drop table t1;
> 
> === added file 'mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt'
> --- a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt	1970-01-01
> 00:00:00 +0000
> +++ b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt	2009-03-18
> 10:31:17 +0000
> @@ -0,0 +1 @@
> +--slave-load-tmpdir=../../../error
> 
> === added file 'mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test'
> --- a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test	1970-01-01 00:00:00
> +0000
> +++ b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test	2009-03-18 10:31:17
> +0000
> @@ -0,0 +1,15 @@
> +##########################################################################
> +# This test verifies if the start slave fails gracefuly when an 
> +# invalid directory is used to set --slave-load-tmpdir.
> +##########################################################################
> +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
> +connect (master1,127.0.0.1,root,,test,$MASTER_MYPORT,);
> +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
> +connect (slave1,127.0.0.1,root,,test,$SLAVE_MYPORT,);
> +
> +connection slave;
> +start slave;
> +
> +source include/wait_for_slave_sql_to_stop.inc;
> +let $error=query_get_value("show slave status", Last_SQL_Error, 1);
> +echo $error;
> 
> === modified file 'sql/log_event.cc'
> --- a/sql/log_event.cc	2009-03-05 10:23:46 +0000
> +++ b/sql/log_event.cc	2009-03-18 10:31:17 +0000
> @@ -382,7 +382,7 @@ static void cleanup_load_tmpdir()
>    uint i;
>    char fname[FN_REFLEN], prefbuf[31], *p;
>  
> -  if (!(dirp=my_dir(slave_load_tmpdir,MYF(MY_WME))))
> +  if (!(dirp=my_dir(slave_load_tmpdir,MYF(0))))
>      return;
>  
>    /* 
> @@ -6178,6 +6178,12 @@ int Append_block_log_event::do_apply_eve
>    thd_proc_info(thd, proc_info);
>    if (get_create_or_append())
>    {
> +    /*
> +      Usually lex_start() is called by mysql_parse(), but we need it here
> +      as the present method does not call mysql_parse().
> +    */
> +    lex_start(thd);
> +    mysql_reset_thd_for_next_command(thd);
>      my_delete(fname, MYF(0)); // old copy may exist already
>      if ((fd= my_create(fname, CREATE_MODE,
>  		       O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
> @@ -6197,6 +6203,10 @@ int Append_block_log_event::do_apply_eve
>                  get_type_str(), fname);
>      goto err;
>    }
> +
> +  DBUG_EXECUTE_IF("remove_slave_load_file_before_write", 
> +                  my_close(fd,MYF(0)); fd= -1; my_delete(fname, MYF(0)););
> +
>    if (my_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP)))
>    {
>      rli->report(ERROR_LEVEL, my_errno,
> 
> === modified file 'sql/slave.cc'
> --- a/sql/slave.cc	2009-01-09 12:49:24 +0000
> +++ b/sql/slave.cc	2009-03-18 10:31:17 +0000
> @@ -2632,6 +2632,41 @@ err:
>    DBUG_RETURN(0);                               // Can't return anything here
>  }
>  
> +/*
> +  Check the temporary directory used by commands like
> +  LOAD DATA INFILE.
> + */
> +static 
> +int check_temp_dir(char* tmp_dir, char *tmp_file)
> +{
> +  int fd;
> +  MY_DIR *dirp;
> +
> +  DBUG_ENTER("check_temp_dir");
> +
> +  /*
> +    Check if the directory exists.
> +   */
> +  if (!(dirp=my_dir(tmp_dir,MYF(MY_WME))))
> +    DBUG_RETURN(1);
> +  my_dirend(dirp);
> +
> +  /*
> +    Check permissions to create a file.
> +   */
> +  if ((fd= my_create(tmp_file, CREATE_MODE,
> +                     O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
> +                     MYF(MY_WME))) < 0)
> +  DBUG_RETURN(1);
> +
> +  /*
> +    Clean up.
> +   */
> +  my_close(fd, MYF(0));
> +  my_delete(tmp_file, MYF(0));
> +
> +  DBUG_RETURN(0);
> +}
>  
>  /**
>    Slave SQL thread entry point.
> @@ -2763,6 +2798,14 @@ log '%s' at position %s, relay log '%s' 
>                     
> llstr(rli->group_master_log_pos,llbuff),rli->group_relay_log_name,
>                      llstr(rli->group_relay_log_pos,llbuff1));
>  
> +  if (check_temp_dir(slave_load_tmpdir, rli->slave_patternload_file))
> +  {
> +    rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), 
> +                "Unable to use slave's temporary directory %s - %s", 
> +                slave_load_tmpdir, thd->main_da.message());
> +    goto err;
> +  }
> +
>    /* execute init_slave variable */
>    if (sys_init_slave.value_length)
>    {
> 
> 
> -- 
> MySQL Code Commits Mailing List
> For list archives: http://lists.mysql.com/commits
> To unsubscribe:    http://lists.mysql.com/commits?unsub=1

Thread
bzr commit into mysql-5.1-bugteam branch (alfranio.correia:2832)Bug#42861Alfranio Correia18 Mar
  • Re: bzr commit into mysql-5.1-bugteam branch (alfranio.correia:2832)Bug#42861He Zhenxing19 Mar