Commit d8b2d4a0 authored by Rohit Kalhans's avatar Rohit Kalhans

Bug#11762667: MYSQLBINLOG IGNORES ERRORS WHILE WRITING OUTPUT

Problem: mysqlbinlog exits without any error code in case of
file write error. It is because of the fact that the calls
to Log_event::print() method does not return a value and the
thus any error were being ignored.

Resolution: We resolve this problem by checking for the 
IO_CACHE::error == -1 after every call to Log_event:: print()
and terminating the further execution.

client/mysqlbinlog.cc:
  - handled error conditions during event->print() calls
  - added check for error in end_io_cache()
mysys/my_write.c:
  Added debug code to simulate file write error.
  error returned will be ENOSPC=> error no space on the disk
sql/log_event.cc:
  Added debug code to simulate file write error, by reducing the size of io cache.
parent 01748ce1
...@@ -690,6 +690,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -690,6 +690,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
DBUG_ENTER("process_event"); DBUG_ENTER("process_event");
print_event_info->short_form= short_form; print_event_info->short_form= short_form;
Exit_status retval= OK_CONTINUE; Exit_status retval= OK_CONTINUE;
IO_CACHE *const head= &print_event_info->head_cache;
/* /*
Format events are not concerned by --offset and such, we always need to Format events are not concerned by --offset and such, we always need to
...@@ -753,6 +754,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -753,6 +754,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
} }
else else
ev->print(result_file, print_event_info); ev->print(result_file, print_event_info);
if (head->error == -1)
goto err;
break; break;
case CREATE_FILE_EVENT: case CREATE_FILE_EVENT:
...@@ -804,6 +807,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -804,6 +807,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
output of Append_block_log_event::print is only a comment. output of Append_block_log_event::print is only a comment.
*/ */
ev->print(result_file, print_event_info); ev->print(result_file, print_event_info);
if (head->error == -1)
goto err;
if ((retval= load_processor.process((Append_block_log_event*) ev)) != if ((retval= load_processor.process((Append_block_log_event*) ev)) !=
OK_CONTINUE) OK_CONTINUE)
goto end; goto end;
...@@ -812,6 +817,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -812,6 +817,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
case EXEC_LOAD_EVENT: case EXEC_LOAD_EVENT:
{ {
ev->print(result_file, print_event_info); ev->print(result_file, print_event_info);
if (head->error == -1)
goto err;
Execute_load_log_event *exv= (Execute_load_log_event*)ev; Execute_load_log_event *exv= (Execute_load_log_event*)ev;
Create_file_log_event *ce= load_processor.grab_event(exv->file_id); Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
/* /*
...@@ -841,6 +848,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -841,6 +848,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
print_event_info->common_header_len= print_event_info->common_header_len=
glob_description_event->common_header_len; glob_description_event->common_header_len;
ev->print(result_file, print_event_info); ev->print(result_file, print_event_info);
if (head->error == -1)
goto err;
if (!remote_opt) if (!remote_opt)
ev->free_temp_buf(); // free memory allocated in dump_local_log_entries ev->free_temp_buf(); // free memory allocated in dump_local_log_entries
else else
...@@ -864,6 +873,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -864,6 +873,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
break; break;
case BEGIN_LOAD_QUERY_EVENT: case BEGIN_LOAD_QUERY_EVENT:
ev->print(result_file, print_event_info); ev->print(result_file, print_event_info);
if (head->error == -1)
goto err;
if ((retval= load_processor.process((Begin_load_query_log_event*) ev)) != if ((retval= load_processor.process((Begin_load_query_log_event*) ev)) !=
OK_CONTINUE) OK_CONTINUE)
goto end; goto end;
...@@ -974,6 +985,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -974,6 +985,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
} }
default: default:
ev->print(result_file, print_event_info); ev->print(result_file, print_event_info);
if (head->error == -1)
goto err;
} }
} }
...@@ -2012,7 +2025,13 @@ err: ...@@ -2012,7 +2025,13 @@ err:
end: end:
if (fd >= 0) if (fd >= 0)
my_close(fd, MYF(MY_WME)); my_close(fd, MYF(MY_WME));
end_io_cache(file); /*
Since the end_io_cache() writes to the
file errors may happen.
*/
if (end_io_cache(file))
retval= ERROR_STOP;
return retval; return retval;
} }
......
...@@ -38,7 +38,17 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) ...@@ -38,7 +38,17 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
for (;;) for (;;)
{ {
if ((writenbytes= write(Filedes, Buffer, Count)) == Count) writenbytes= write(Filedes, Buffer, Count);
/**
To simulate the write error set the errno = error code
and the number pf written bytes to -1.
*/
DBUG_EXECUTE_IF ("simulate_file_write_error",
{
errno= ENOSPC;
writenbytes= (size_t) -1;
});
if (writenbytes == Count)
break; break;
if (writenbytes != (size_t) -1) if (writenbytes != (size_t) -1)
{ /* Safeguard */ { /* Safeguard */
......
...@@ -3090,6 +3090,12 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) ...@@ -3090,6 +3090,12 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
{ {
Write_on_release_cache cache(&print_event_info->head_cache, file); Write_on_release_cache cache(&print_event_info->head_cache, file);
/**
reduce the size of io cache so that the write function is called
for every call to my_b_write().
*/
DBUG_EXECUTE_IF ("simulate_file_write_error",
{(&cache)->write_pos= (&cache)->write_end- 500;});
print_query_header(&cache, print_event_info); print_query_header(&cache, print_event_info);
my_b_write(&cache, (uchar*) query, q_len); my_b_write(&cache, (uchar*) query, q_len);
my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); my_b_printf(&cache, "\n%s\n", print_event_info->delimiter);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment