Skip to content

Commit c72f687

Browse files
author
Venkatesh Duggirala
committed
BUG#11753923-SQL THREAD CRASHES ON DISK FULL
Problem:If Disk becomes full while writing into the binlog, then the server instance hangs till someone frees the space. After user frees up the disk space, mysql server crashes with an assert (m_status != DA_EMPTY) Analysis: wait_for_free_space is being called in an infinite loop i.e., server instance will hang until someone frees up the space. So there is no need to set status bit in diagnostic area. Fix: Replace my_error/my_printf_error with sql_print_warning() which prints the warning in error log.
1 parent f5f40ba commit c72f687

File tree

5 files changed

+47
-6
lines changed

5 files changed

+47
-6
lines changed

include/my_sys.h

+2
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ extern char *home_dir; /* Home directory for user */
234234
extern const char *my_progname; /* program-name (printed in errors) */
235235
extern char NEAR curr_dir[]; /* Current directory for user */
236236
extern int (*error_handler_hook)(uint my_err, const char *str,myf MyFlags);
237+
extern void(*sql_print_warning_hook)(const char *format,...);
237238
extern int (*fatal_error_handler_hook)(uint my_err, const char *str,
238239
myf MyFlags);
239240
extern uint my_file_limit;
@@ -675,6 +676,7 @@ extern int my_error _VARARGS((int nr,myf MyFlags, ...));
675676
extern int my_printf_error _VARARGS((uint my_err, const char *format,
676677
myf MyFlags, ...))
677678
ATTRIBUTE_FORMAT(printf, 2, 4);
679+
extern void my_printf_warning _VARARGS((const char * format, ...));
678680
extern int my_error_register(const char **errmsgs, int first, int last);
679681
extern const char **my_error_unregister(int first, int last);
680682
extern int my_message(uint my_err, const char *str,myf MyFlags);

mysys/errors.c

+18-6
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,28 @@ void init_glob_errs()
101101
}
102102
#endif
103103

104+
/*
105+
We cannot call my_error/my_printf_error here in this function.
106+
Those functions will set status variable in diagnostic area
107+
and there is no provision to reset them back.
108+
Here we are waiting for free space and will wait forever till
109+
space is created. So just giving warning in the error file
110+
should be enough.
111+
*/
104112
void wait_for_free_space(const char *filename, int errors)
105113
{
106-
if (errors == 0)
107-
my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH),
108-
filename,my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC);
109114
if (!(errors % MY_WAIT_GIVE_USER_A_MESSAGE))
110-
my_printf_error(EE_DISK_FULL,
111-
"Retry in %d secs. Message reprinted in %d secs",
112-
MYF(ME_BELL | ME_NOREFRESH),
115+
{
116+
my_printf_warning(EE(EE_DISK_FULL),
117+
filename,my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC);
118+
my_printf_warning("Retry in %d secs. Message reprinted in %d secs",
113119
MY_WAIT_FOR_USER_TO_FIX_PANIC,
114120
MY_WAIT_GIVE_USER_A_MESSAGE * MY_WAIT_FOR_USER_TO_FIX_PANIC );
121+
}
122+
DBUG_EXECUTE_IF("simulate_file_write_error_once",
123+
{
124+
VOID(sleep(1));
125+
return;
126+
});
115127
VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC));
116128
}

mysys/my_error.c

+22
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,28 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...)
128128
DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags));
129129
}
130130

131+
/*
132+
Warning as printf
133+
134+
SYNOPSIS
135+
my_printf_warning()
136+
format> Format string
137+
...> variable list
138+
*/
139+
void(*sql_print_warning_hook)(const char *format,...);
140+
void my_printf_warning(const char *format, ...)
141+
{
142+
va_list args;
143+
char wbuff[ERRMSGSIZE];
144+
DBUG_ENTER("my_printf_warning");
145+
DBUG_PRINT("my", ("Format: %s", format));
146+
va_start(args,format);
147+
(void) my_vsnprintf (wbuff, sizeof(wbuff), format, args);
148+
va_end(args);
149+
(*sql_print_warning_hook)(wbuff);
150+
DBUG_VOID_RETURN;
151+
}
152+
131153
/*
132154
Give message using error_handler_hook
133155

mysys/my_write.c

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
3636
if (unlikely(!Count))
3737
DBUG_RETURN(0);
3838

39+
DBUG_EXECUTE_IF ("simulate_file_write_error_once",
40+
{ DBUG_SET("+d,simulate_file_write_error");});
3941
for (;;)
4042
{
4143
writenbytes= write(Filedes, Buffer, Count);
@@ -69,6 +71,8 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
6971
{
7072
wait_for_free_space(my_filename(Filedes), errors);
7173
errors++;
74+
DBUG_EXECUTE_IF("simulate_file_write_error_once",
75+
{ DBUG_SET("-d,simulate_file_write_error");});
7276
continue;
7377
}
7478

sql/mysqld.cc

+1
Original file line numberDiff line numberDiff line change
@@ -4375,6 +4375,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
43754375
After this we can't quit by a simple unireg_abort
43764376
*/
43774377
error_handler_hook= my_message_sql;
4378+
sql_print_warning_hook = sql_print_warning;
43784379
start_signal_handler(); // Creates pidfile
43794380

43804381
if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||

0 commit comments

Comments
 (0)