summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Nozdrin <alexander.nozdrin@oracle.com>2011-09-22 18:31:16 +0400
committerAlexander Nozdrin <alexander.nozdrin@oracle.com>2011-09-22 18:31:16 +0400
commit41dc3049281c1718e49d80eaf0cf068def9519b5 (patch)
tree8a1d75b95a1c82e444020c7e53d303b13cf3f9bd /sql
parenta2cd617a4bfd5fe8d99c9bcda450c8e0579d7a6b (diff)
downloadmariadb-git-41dc3049281c1718e49d80eaf0cf068def9519b5.tar.gz
Fix for Bug#13001491: MYSQL_REFRESH CRASHES WHEN STORED ROUTINES ARE RUN CONCURRENTLY.
The main problem was that lex_start() was forgotten to be called before processing COM_REFRESH. Another problem discovered was that if failures to flush the error log were not properly handled, which resulted in the server crash. The user-visible effect of these problems were: - if COM_REFRESH command was sent after SQL-queries of some sort, the server would crash. - if COM_REFRESH was requested with REFRESH_LOG only, and the error log failed to flush, the server would crash. The error log fails to flush when it points to unavailable file (for example, due to restricted permissions). The fixes are: - call lex_start() in the beginning of COM_REFRESH; - handle failures to flush the error log properly, i.e. raise ER_UNKNOWN_ERROR.
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_parse.cc44
1 files changed, 39 insertions, 5 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 2eeabc2f0c1..b5864fef19d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1491,6 +1491,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_REFRESH:
{
int not_used;
+
+ /*
+ Initialize thd->lex since it's used in many base functions, such as
+ open_tables(). Otherwise, it remains unitialized and may cause crash
+ during execution of COM_REFRESH.
+ */
+ lex_start(thd);
+
status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]);
ulong options= (ulong) (uchar) packet[0];
if (check_global_access(thd,RELOAD_ACL))
@@ -6986,7 +6994,14 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
if (ha_flush_logs(NULL))
result=1;
if (flush_error_log())
- result=1;
+ {
+ /*
+ When flush_error_log() failed, my_error() has not been called.
+ So, we have to do it here to keep the protocol.
+ */
+ my_error(ER_UNKNOWN_ERROR, MYF(0));
+ result= 1;
+ }
}
#ifdef HAVE_QUERY_CACHE
if (options & REFRESH_QUERY_CACHE_FREE)
@@ -7035,7 +7050,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
return 1; // Killed
if (close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
FALSE : TRUE, TRUE))
- result= 1;
+ {
+ /*
+ NOTE: my_error() has been already called by reopen_tables() within
+ close_cached_tables().
+ */
+ result= 1;
+ }
if (make_global_read_lock_block_commit(thd)) // Killed
{
@@ -7048,7 +7069,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
{
if (close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
FALSE : TRUE, FALSE))
+ {
+ /*
+ NOTE: my_error() has been already called by reopen_tables() within
+ close_cached_tables().
+ */
result= 1;
+ }
}
my_dbopt_cleanup();
}
@@ -7065,7 +7092,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
tmp_write_to_binlog= 0;
if (reset_master(thd))
{
- result=1;
+ /* NOTE: my_error() has been already called by reset_master(). */
+ result= 1;
}
}
#endif
@@ -7073,7 +7101,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
if (options & REFRESH_DES_KEY_FILE)
{
if (des_key_file && load_des_key_file(des_key_file))
- result= 1;
+ {
+ /* NOTE: my_error() has been already called by load_des_key_file(). */
+ result= 1;
+ }
}
#endif
#ifdef HAVE_REPLICATION
@@ -7082,7 +7113,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
tmp_write_to_binlog= 0;
pthread_mutex_lock(&LOCK_active_mi);
if (reset_slave(thd, active_mi))
- result=1;
+ {
+ /* NOTE: my_error() has been already called by reset_slave(). */
+ result= 1;
+ }
pthread_mutex_unlock(&LOCK_active_mi);
}
#endif