#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-13
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 changing 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 cleanup function however was being failing and an error thrown by
my_dir and the replication SQL thread was not aborting its execution.
To fix the problem we check the directory before starting the replication.
added:
mysql-test/suite/rpl/r/rpl_slave_fail_load_in.result
mysql-test/suite/rpl/t/rpl_slave_fail_load_in-slave.opt
mysql-test/suite/rpl/t/rpl_slave_fail_load_in.test
renamed:
mysql-test/suite/rpl/r/rpl_slave_load_in.result => mysql-test/suite/rpl/r/rpl_slave_pass_load_in.result
mysql-test/suite/rpl/t/rpl_slave_load_in.test => mysql-test/suite/rpl/t/rpl_slave_pass_load_in.test
modified:
sql/rpl_rli.cc
=== added file 'mysql-test/suite/rpl/r/rpl_slave_fail_load_in.result'
--- a/mysql-test/suite/rpl/r/rpl_slave_fail_load_in.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_slave_fail_load_in.result 2009-03-13 11:02:30 +0000
@@ -0,0 +1,2 @@
+START SLAVE;
+ERROR HY000: Can't read dir of '../../../error' (Errcode: 2)
=== renamed file 'mysql-test/suite/rpl/r/rpl_slave_load_in.result' => 'mysql-test/suite/rpl/r/rpl_slave_pass_load_in.result'
=== added file 'mysql-test/suite/rpl/t/rpl_slave_fail_load_in-slave.opt'
--- a/mysql-test/suite/rpl/t/rpl_slave_fail_load_in-slave.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_slave_fail_load_in-slave.opt 2009-03-13 11:02:30 +0000
@@ -0,0 +1 @@
+--slave-load-tmpdir=../../../error
=== added file 'mysql-test/suite/rpl/t/rpl_slave_fail_load_in.test'
--- a/mysql-test/suite/rpl/t/rpl_slave_fail_load_in.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_slave_fail_load_in.test 2009-03-13 11:02:30 +0000
@@ -0,0 +1,13 @@
+##########################################################################
+# This test verifies if the start slave fails 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;
+
+--error 12
+START SLAVE;
=== renamed file 'mysql-test/suite/rpl/t/rpl_slave_load_in.test' => 'mysql-test/suite/rpl/t/rpl_slave_pass_load_in.test'
=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc 2009-02-22 13:40:52 +0000
+++ b/sql/rpl_rli.cc 2009-03-13 11:02:30 +0000
@@ -80,6 +80,40 @@ Relay_log_info::~Relay_log_info()
DBUG_VOID_RETURN;
}
+/*
+ Check the temporary directory used by commands like
+ LOAD DATA INFILE.
+ */
+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);
+}
int init_relay_log_info(Relay_log_info* rli,
const char* info_fname)
@@ -109,6 +143,12 @@ int init_relay_log_info(Relay_log_info*
MY_RETURN_REAL_PATH);
rli->slave_patternload_file_size= strlen(rli->slave_patternload_file);
+ if (check_temp_dir(slave_load_tmpdir, rli->slave_patternload_file))
+ {
+ pthread_mutex_unlock(&rli->data_lock);
+ DBUG_RETURN(1);
+ }
+
/*
The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
Note that the I/O thread flushes it to disk after writing every