List:Commits« Previous MessageNext Message »
From:Rafal Somla Date:December 8 2008 12:13pm
Subject:bzr commit into mysql-6.0-backup branch (Rafal.Somla:2740) Bug#35079 WL#4538
View as plain text  
#At file:///ext/mysql/bzr/backup/wl4538-new/

 2740 Rafal Somla	2008-12-08
      BUG#35079/WL#4538 - Make BACKUP/RESTORE statements interruptible.
      
      The server detects interruptions in statement execution such as when client 
      connection is closed or if user hits Ctrl+C. However, the code inside the server 
      must actively check if an interruption has happened and abort execution in that 
      case.
      
      This patch adds such checks to the backup code, as described in WL#4538. After 
      this patch it should be possible to interrupt on-going BACKUP/RESTORE command. 
      It also fixes few problems in the code so that the new tests can pass through.
added:
  mysql-test/suite/backup/r/backup_intr_errors.result
  mysql-test/suite/backup/t/backup_intr_errors.test
  mysql-test/suite/backup_engines/include/backup_restore_interrupt.inc
  mysql-test/suite/backup_engines/r/backup_interruption.result
  mysql-test/suite/backup_engines/t/backup_interruption.test
modified:
  mysql-test/lib/mtr_report.pl
  sql/backup/backup_kernel.h
  sql/backup/be_default.h
  sql/backup/be_snapshot.h
  sql/backup/be_thread.cc
  sql/backup/be_thread.h
  sql/backup/data_backup.cc
  sql/backup/kernel.cc
  sql/backup/logger.cc
  sql/backup/logger.h
  sql/backup/stream.cc
  sql/backup/stream.h
  sql/share/errmsg.txt

per-file messages:
  mysql-test/lib/mtr_report.pl
    Suppress detection by mtr expected errors during backup_intr_errors test.
  mysql-test/suite/backup/t/backup_intr_errors.test
    New test which checks error reporting after an interruption.
  mysql-test/suite/backup_engines/include/backup_restore_interrupt.inc
    A helper "subroutine" for the interruption tests.
  mysql-test/suite/backup_engines/t/backup_interruption.test
    The main test for interruptions.
  sql/backup/backup_kernel.h
    Remove incorrect code. Setting m_remove_loc to TRUE always when fatal
    error is encountered is not correct because, for example, error can 
    happen when BACKUP tries to overwrite existing file. Setting m_remove_loc
    to TRUE in this case will result in BACKUP deleting the file on exit
    which is bad. Instead, the m_remove_loc flag is correctly handled in 
    prepare_for_backup() and do_backup() methods.
  sql/backup/be_default.h
    Add error injection code.
  sql/backup/be_snapshot.h
    Add error injection code.
  sql/backup/be_thread.cc
    Fix possible deadlock when the Locking_thread_st destructor is waiting
    for a locking thread which has not been started before.
  sql/backup/be_thread.h
    Add m_thread_started member to Locking_thread_st.
  sql/backup/data_backup.cc
    - Fix error in write_table_data() logic which caused the commit blocker to not 
      be deactivated if error branch was executed.
    - Add checks for interruptions in various stages of backup and restore protocol, 
      including  Scheduler::step() which is the main worker method in 
      write_table_data().
    - Add explicit log_level::ERROR to report_error() where needed.
    - Add extra debug sync points needed for testing.
  sql/backup/kernel.cc
    - Add more debug sync points needed for testing.
    - Add checks for interruption inside Backup_restore_ctx methods,
      at various stages of executing BACKUP/RESTORE statement.
    - Inside prepare*() methods, move the place where m_catalog is 
      assigned so that it is always deleted in the destructor.
    - Use explicit log_level::ERROR when needed.
    - Fix Backup_restore_ctx::close() to always call report_stop()
      matching previous report_start().
    - Fix possible memory leak in Backup_restore_ctx::restore_triggers_and_events().
    - Move the temporary cleanup code needed after restoring triggers and events 
      from do_restore() to restore_triggers_and_events() so that it is always 
      executed.
  sql/backup/logger.cc
    Add Logger::report_killed() method.
  sql/backup/logger.h
    - Declare report_error() method.
    - Declare variant of log_error() which does not detect interruptions.
    - Add m_kill_reported flag.
    - Change semantics of report_error() and log_error() so that they detect
      and report interruptions.
  sql/backup/stream.cc
    Add error injection code.
  sql/backup/stream.h
    Move the temporary cleanup code to the wrapper function read_meta_data() so that 
    we don't have to depend on the caller for executing it.
  sql/share/errmsg.txt
    Add message used to notify about an interruption of BACKUP/RESTORE operations.
=== modified file 'mysql-test/lib/mtr_report.pl'
--- a/mysql-test/lib/mtr_report.pl	2008-11-21 15:02:34 +0000
+++ b/mysql-test/lib/mtr_report.pl	2008-12-08 12:13:32 +0000
@@ -392,6 +392,17 @@ sub mtr_report_stats ($) {
 		
                 ($testname eq 'backup.backup_myisam1') and
                 (/Backup: Can't initialize MyISAM backup driver/) or
+
+                ($testname eq 'backup.backup_intr_errors') and
+		(
+                  # ignore errors triggered on purpose during BACKUP/RESTORE 
+                  # operation shutdown
+		  /Backup: .* backup driver can't cancel its backup operation/ or
+		  /Backup: Error on delete of/ or
+		  /Error on close of backup stream/ or
+		  /Restore: Can't shut down .* restore driver/
+		) or
+
 		/Sort aborted/ or
 		/Time-out in NDB/ or
 		/One can only use the --user.*root/ or

=== added file 'mysql-test/suite/backup/r/backup_intr_errors.result'
--- a/mysql-test/suite/backup/r/backup_intr_errors.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_intr_errors.result	2008-12-08 12:13:32 +0000
@@ -0,0 +1,268 @@
+#
+# Setup
+#
+DROP DATABASE IF EXISTS bup_intr;
+CREATE DATABASE bup_intr;
+USE bup_intr;
+CREATE TABLE t1(engine char(6));
+INSERT INTO  t1 VALUES ('innodb'),('memory');
+CREATE TABLE t2(a int);
+INSERT INTO t2 VALUES (1);
+DELETE FROM bup_intr.t1 WHERE engine='innodb';
+
+########################################
+## Testing with innodb engine.
+########################################
+
+ALTER TABLE bup_intr.t1 ENGINE=innodb;
+SET SESSION DEBUG="+d,backup_driver_cancel_error";
+SET SESSION DEBUG="+d,backup_stream_close_error";
+SET SESSION DEBUG="+d,backup_remove_location_error";
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_data_lock.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_data_lock SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_data_lock
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Snapshot backup driver can't cancel its backup operation
+Error	<error-code>	Backup/Restore: Error on close of backup stream
+Error	<error-code>	Error on delete of <backup image path> (errno: 176)
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+backup kernel	0	validity point
+SELECT * FROM mysql.backup_history;
+SET SESSION DEBUG="-d";
+#
+# Prepare bup_intr.bkp for RESTORE testing. Note that above BACKUP
+# command should not create the file because it was interrupted.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+backup_id
+#
+DROP DATABASE bup_intr;
+SET SESSION DEBUG="+d,backup_driver_cancel_error";
+SET SESSION DEBUG="+d,backup_stream_close_error";
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point restore_before_sending_data.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='restore_before_sending_data SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: restore_before_sending_data
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Can't shut down Snapshot restore driver(s)
+Error	<error-code>	Backup/Restore: Error on close of backup stream
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+SET SESSION DEBUG="-d";
+#
+# Restore original database - the interrupted RESTORE statement could
+# corrupt it.
+#
+RESTORE FROM 'bup_intr.bkp' OVERWRITE;
+backup_id
+#
+DELETE FROM bup_intr.t1 WHERE engine='memory';
+
+########################################
+## Testing with memory engine.
+########################################
+
+ALTER TABLE bup_intr.t1 ENGINE=memory;
+SET SESSION DEBUG="+d,backup_driver_cancel_error";
+SET SESSION DEBUG="+d,backup_stream_close_error";
+SET SESSION DEBUG="+d,backup_remove_location_error";
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_data_lock.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_data_lock SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_data_lock
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Default backup driver can't cancel its backup operation
+Error	<error-code>	Backup/Restore: Error on close of backup stream
+Error	<error-code>	Error on delete of <backup image path> (errno: 176)
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+backup kernel	0	validity point
+SELECT * FROM mysql.backup_history;
+SET SESSION DEBUG="-d";
+#
+# Prepare bup_intr.bkp for RESTORE testing. Note that above BACKUP
+# command should not create the file because it was interrupted.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+backup_id
+#
+DROP DATABASE bup_intr;
+SET SESSION DEBUG="+d,backup_driver_cancel_error";
+SET SESSION DEBUG="+d,backup_stream_close_error";
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point restore_before_sending_data.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='restore_before_sending_data SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: restore_before_sending_data
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+Error	<error-code>	Can't shut down Default restore driver(s)
+Error	<error-code>	Backup/Restore: Error on close of backup stream
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+SET SESSION DEBUG="-d";
+#
+# Restore original database - the interrupted RESTORE statement could
+# corrupt it.
+#
+RESTORE FROM 'bup_intr.bkp' OVERWRITE;
+backup_id
+#
+#
+# Cleanup
+#
+DROP DATABASE IF EXISTS bup_intr;

=== added file 'mysql-test/suite/backup/t/backup_intr_errors.test'
--- a/mysql-test/suite/backup/t/backup_intr_errors.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_intr_errors.test	2008-12-08 12:13:32 +0000
@@ -0,0 +1,122 @@
+#
+# This test checks what happens if errors occur during BACKUP/RESTORE shutdown
+# sequence in case of interruption of one of these statements. The errors are
+# triggered using error injection code. They should be reported on server's 
+# error stack after the standard "Query execution was interrupted" error. The
+# latter error should be reported by the interrupted statement.
+#
+
+--source include/not_embedded.inc
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+
+--echo #
+--echo # Setup
+--echo #
+let $bdir=`SELECT @@backupdir`;
+
+--disable_warnings
+DROP DATABASE IF EXISTS bup_intr;
+--error 0,1
+--remove_file $bdir/bup_intr.bkp
+--enable_warnings
+
+CREATE DATABASE bup_intr;
+USE bup_intr;
+
+CREATE TABLE t1(engine char(6));
+#
+# Table t1 is used in the test loop which will iterate over its rows and
+# change t1's storage engine as indicated. We pick innodb and memory to 
+# trigger use of the default and the snapshot backup/restore drivers.
+#
+INSERT INTO  t1 VALUES ('innodb'),('memory');
+#
+# Table t2 is here so that some table data is always stored in the image
+# and the synchronization point used below is always reached.
+#
+CREATE TABLE t2(a int);
+INSERT INTO t2 VALUES (1);
+
+# connection required by backup_restore_interrupt.inc
+--connect (killer,localhost,root,,)
+
+#
+# Loop over rows in t1 which indicate what storage engine should be used.
+#
+
+while (`SELECT count(*) > 0 FROM bup_intr.t1`)
+{
+
+  # read the next engine and remove it from t1
+  let $engine=`SELECT engine FROM bup_intr.t1 LIMIT 1`;
+  eval DELETE FROM bup_intr.t1 WHERE engine='$engine';
+
+  --echo
+  --echo ########################################
+  --echo ## Testing with $engine engine.
+  --echo ########################################
+  --echo
+
+  # change storage engine of t1
+  eval ALTER TABLE bup_intr.t1 ENGINE=$engine;
+
+  #
+  # Test interruption of BACKUP
+  #
+  let $do_restore=0;
+  # activate error injection code
+  SET SESSION DEBUG="+d,backup_driver_cancel_error";
+  SET SESSION DEBUG="+d,backup_stream_close_error";
+  SET SESSION DEBUG="+d,backup_remove_location_error";
+  #
+  # Test interruption in the middle of BACKUP operation, just before VP
+  # is created.
+  #
+  let $sync_point=before_backup_data_lock;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+  SET SESSION DEBUG="-d";
+
+  --echo #
+  --echo # Prepare bup_intr.bkp for RESTORE testing. Note that above BACKUP
+  --echo # command should not create the file because it was interrupted.
+  --echo #
+  --replace_column 1 #
+  BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+  DROP DATABASE bup_intr;
+
+  #
+  # Test interruption of RESTORE
+  #
+  let $do_restore=1;
+  # activate error injection code
+  SET SESSION DEBUG="+d,backup_driver_cancel_error";
+  SET SESSION DEBUG="+d,backup_stream_close_error";
+  #
+  # Test interruption of RESTORE when the first block of table data is
+  # sent to a restore driver.
+  #
+  let $sync_point=restore_before_sending_data;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+  SET SESSION DEBUG="-d";
+
+  --echo #
+  --echo # Restore original database - the interrupted RESTORE statement could
+  --echo # corrupt it.
+  --echo #
+  --replace_column 1 #
+  RESTORE FROM 'bup_intr.bkp' OVERWRITE;
+  --remove_file $bdir/bup_intr.bkp
+
+} # end of the while loop.
+
+--echo #
+--echo # Cleanup
+--echo #
+--disable_warnings
+DROP DATABASE IF EXISTS bup_intr;
+--error 0,1
+--remove_file $bdir/bup_intr.bkp
+--enable_warnings
+

=== added file 'mysql-test/suite/backup_engines/include/backup_restore_interrupt.inc'
--- a/mysql-test/suite/backup_engines/include/backup_restore_interrupt.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup_engines/include/backup_restore_interrupt.inc	2008-12-08 12:13:32 +0000
@@ -0,0 +1,106 @@
+#
+# This is a "subroutine" for backup_interrupt.test. It performs the following:
+#
+# 1. Start BACKUP or RESTORE statement and use a synchronization point
+#    to stop it in the middle of execution.
+# 2. In another connection, wait for the statement to reach the synchronization
+#    point, and then KILL it.
+# 3. Signal the stopped BACKUP/RESTORE statement so that it resumes execution
+#    after being killed.
+# 4. Check the error response from the statement, contents of the error stack
+#    and backup logs.
+#
+# Variable $do_restore determines whether BACKUP or RESTORE is executed. The
+# synchronization point to use is stored in $sync_point. 
+#
+# This script uses the following assumptions, which must be satisfied by 
+# its user:
+#
+# - $bdir holds the current value of @@backupdir variable.
+# - There is a second connection named 'killer'.
+# - There exists database called 'bup_intr'.
+# - If $do_restore = 1 then $bdir/bup_intr.bkp should contain valid backup 
+#   image.
+#
+
+let $command= BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+
+if ($do_restore)
+{
+  let $command= RESTORE FROM 'bup_intr.bkp';
+}
+
+--echo 
+--echo ######################################################################
+--echo #
+--echo # Testing interruption of command $command
+--echo # at synchronization point $sync_point.
+--echo #
+--echo ######################################################################
+--echo 
+--connection default
+
+let $id=`select connection_id()`;
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+eval SET DEBUG_SYNC='$sync_point SIGNAL here WAIT_FOR go';
+#
+# Arrange for 'here' signal to be always sent at the end of BACKUP/RESTORE 
+# operation (in the destructor of backup/restore context class). This way
+# test will not hang waiting for the signal even if $sync_point is invalid 
+# or never hit. The fact that we missed the requested synchronization point
+# will be detected with a SELECT from I_S.PROCESSLIST (see below). Also,
+# the reply from BACKUP/RESTORE will not be the expected ER_QUERY_INTERRUPTED
+# error in most cases.
+#
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+
+--echo #
+--echo # Start the command.
+--echo #
+--send
+eval $command;
+
+  --connection killer
+
+  --echo #
+  --echo # Wait for the command to reach its synchronization point,
+  --echo # then kill it.
+  --echo #
+  SET DEBUG_SYNC='now WAIT_FOR here';
+  --replace_regex /id=[0-9]+/id=<query id>/
+  eval SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=$id;
+  --replace_regex /QUERY [0-9]+/QUERY <query id>/
+  eval KILL QUERY $id;
+  SET DEBUG_SYNC='now SIGNAL go';
+
+--connection default
+
+--echo #
+--echo # Reap the command and show results.
+--echo #
+--error ER_QUERY_INTERRUPTED
+reap;
+--replace_column 2 <error-code>
+# One error message contains file path - mask it out.
+--replace_regex /Error on delete of '.*'/Error on delete of <backup image path>/
+SHOW WARNINGS;
+
+--echo #
+--echo # Examine backup logs.
+--echo #
+--echo # FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+--echo # seen in backup_progress table and backup_history table will be empty.
+--echo # When the bug is fixed the output below will change and the result file
+--echo # should be modifed accordingly.
+--echo #
+SELECT object, error_num, notes FROM mysql.backup_progress;
+query_vertical SELECT * FROM mysql.backup_history;
+
+# check that backup image file was removed
+if (!$do_restore)
+{
+  --error 1
+  --remove_file $bdir/bup_intr.bkp
+}

=== added file 'mysql-test/suite/backup_engines/r/backup_interruption.result'
--- a/mysql-test/suite/backup_engines/r/backup_interruption.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup_engines/r/backup_interruption.result	2008-12-08 12:13:32 +0000
@@ -0,0 +1,1909 @@
+SHOW VARIABLES LIKE 'storage_engine';
+Variable_name	Value
+storage_engine	#
+DROP DATABASE IF EXISTS bup_intr;
+CREATE DATABASE bup_intr;
+USE bup_intr;
+CREATE TABLE t1(a int);
+INSERT INTO  t1 VALUES (1),(2),(3);
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_command.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_command SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_command
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_prepare.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_prepare SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_prepare
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_logger_init.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_logger_init SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_logger_init
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_common_prepare.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_common_prepare SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_common_prepare
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_privileges.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_privileges SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_privileges
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_single_op.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_single_op SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_single_op
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_ddl_block.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_ddl_block SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_ddl_block
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_stream_open.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_stream_open SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_stream_open
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_catalog.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_catalog SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_catalog
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point after_backup_start_backup.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='after_backup_start_backup SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: after_backup_start_backup
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_do_backup.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_do_backup SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_do_backup
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_meta.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_meta SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_meta
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point backup_before_write_preamble.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='backup_before_write_preamble SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: backup_before_write_preamble
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_data.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_data SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_data
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_data_init.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_data_init SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_data_init
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_data_prepare.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_data_prepare SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_data_prepare
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_data_lock.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_data_lock SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_data_lock
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+backup kernel	0	validity point
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_data_unlock.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_data_unlock SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_data_unlock
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+backup kernel	0	validity point
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point after_backup_binlog.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='after_backup_binlog SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: after_backup_binlog
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+backup kernel	0	validity point
+backup kernel	0	vp time
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_data_finish.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_data_finish SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_data_finish
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+backup kernel	0	validity point
+backup kernel	0	vp time
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command BACKUP DATABASE bup_intr TO 'bup_intr.bkp'
+# at synchronization point before_backup_summary.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_backup_summary SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_backup_summary
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+backup kernel	0	validity point
+backup kernel	0	vp time
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+backup_id
+#
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_prepare.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_prepare SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_prepare
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_logger_init.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_logger_init SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_logger_init
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_common_prepare.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_common_prepare SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_common_prepare
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_stream_open.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_stream_open SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_stream_open
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_catalog.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_catalog SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_catalog
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_read_header.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_read_header SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_read_header
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_read_catalog.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_read_catalog SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_read_catalog
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_binlog.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_binlog SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_binlog
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point after_backup_start_restore.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='after_backup_start_restore SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: after_backup_start_restore
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_fkey_disable.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_fkey_disable SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_fkey_disable
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_read_metadata.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_read_metadata SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_read_metadata
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_lock_tables.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_lock_tables SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_lock_tables
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_table_data.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_table_data SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_table_data
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point restore_before_drivers_create.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='restore_before_drivers_create SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: restore_before_drivers_create
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point restore_before_drivers_init.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='restore_before_drivers_init SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: restore_before_drivers_init
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point restore_before_read_data_chunk.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='restore_before_read_data_chunk SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: restore_before_read_data_chunk
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point restore_before_sending_data.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='restore_before_sending_data SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: restore_before_sending_data
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point restore_table_data_before_end.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='restore_table_data_before_end SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: restore_table_data_before_end
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_triggers.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_triggers SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_triggers
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE bup_intr;
+
+######################################################################
+#
+# Testing interruption of command RESTORE FROM 'bup_intr.bkp'
+# at synchronization point before_restore_read_summary.
+#
+######################################################################
+
+PURGE BACKUP LOGS;
+SET DEBUG_SYNC='reset';
+SET DEBUG_SYNC='before_restore_read_summary SIGNAL here WAIT_FOR go';
+SET DEBUG_SYNC='backup_restore_ctx_dtor SIGNAL here';
+#
+# Start the command.
+#
+RESTORE FROM 'bup_intr.bkp';
+#
+# Wait for the command to reach its synchronization point,
+# then kill it.
+#
+SET DEBUG_SYNC='now WAIT_FOR here';
+SELECT state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id=<query id>;
+state
+debug sync point: before_restore_read_summary
+KILL QUERY <query id>;
+SET DEBUG_SYNC='now SIGNAL go';
+#
+# Reap the command and show results.
+#
+ERROR 70100: Query execution was interrupted
+SHOW WARNINGS;
+Level	Code	Message
+Error	<error-code>	Query execution was interrupted
+#
+# Examine backup logs.
+#
+# FIXME: Until BUG#39924 is fixed, change to BUP_CANCEL state will not be
+# seen in backup_progress table and backup_history table will be empty.
+# When the bug is fixed the output below will change and the result file
+# should be modifed accordingly.
+#
+SELECT object, error_num, notes FROM mysql.backup_progress;
+object	error_num	notes
+backup kernel	0	starting
+backup kernel	0	running
+SELECT * FROM mysql.backup_history;
+DROP DATABASE IF EXISTS bup_intr;

=== added file 'mysql-test/suite/backup_engines/t/backup_interruption.test'
--- a/mysql-test/suite/backup_engines/t/backup_interruption.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup_engines/t/backup_interruption.test	2008-12-08 12:13:32 +0000
@@ -0,0 +1,261 @@
+#
+# This test checks that BACKUP/TESTORE commands behave correctly when
+# interrupted. The test strategy is as follows:
+#
+# 1. Start BACKUP or RESTORE statement and use a synchronization point
+#    to stop it in the middle of execution.
+# 2. In another connection, wait for the statement to reach the synchronization
+#    point, and then KILL it.
+# 3. Signal the stopped BACKUP/RESTORE statement so that it resumes execution
+#    after being killed.
+# 4. Check the error response from the statement, contents of the error stack
+#    and backup logs.
+# 
+# Above 4 steps are performed inside backup_restore_interrupt.inc "subroutine"
+# which is executed from this script for various synchronization points inside
+# BACKUP and RESTORE commands.
+#
+# Note: Because of BUG#39924, an interruption is not traced within 
+# backup_progress log and backup_history log entry for an interrupted statement
+# is not written. When the bug is fixed, the output of this test will change 
+# and the result file should be updated after careful inspection.
+#
+--source include/not_embedded.inc
+--source suite/backup_engines/include/backup_engine.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+
+#
+# Setup
+#
+
+let $bdir=`SELECT @@backupdir`;
+
+--disable_warnings
+DROP DATABASE IF EXISTS bup_intr;
+--error 0,1
+--remove_file $bdir/bup_intr.bkp
+--enable_warnings
+
+CREATE DATABASE bup_intr;
+USE bup_intr;
+
+CREATE TABLE t1(a int);
+INSERT INTO  t1 VALUES (1),(2),(3);
+
+# connection required by backup_restore_interrupt.inc
+--connect (killer,localhost,root,,)
+
+#
+# Test BACKUP interruptions.
+#
+
+let $do_restore=0;
+
+# at the very beginning		
+let $sync_point= before_backup_command;
+--source suite/backup_engines/include/backup_restore_interrupt.inc
+
+# before preparations
+let $sync_point= before_backup_prepare;
+--source suite/backup_engines/include/backup_restore_interrupt.inc
+
+# during preparations
+  # before logger initialization
+  let $sync_point= before_backup_logger_init;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+  
+  # before common preparations
+  let $sync_point= before_backup_common_prepare;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # during common preparations
+    # before checking privileges
+    let $sync_point= before_backup_privileges;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+  
+    # before checking that no other BACKUP/RESTORE is running
+    let $sync_point= before_backup_single_op;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+    # before blocking DDLs
+    let $sync_point= before_backup_ddl_block;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # before openning the stream
+  let $sync_point= before_backup_stream_open;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # before creating catalogue
+  let $sync_point= before_backup_catalog;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+# before populating backup catalogue
+let $sync_point= after_backup_start_backup;
+--source suite/backup_engines/include/backup_restore_interrupt.inc
+
+# before do_backup
+let $sync_point= before_do_backup;
+--source suite/backup_engines/include/backup_restore_interrupt.inc
+
+# inside do_backup
+  # before preamble is written
+  let $sync_point= before_backup_meta;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+  let $sync_point= backup_before_write_preamble;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # before write_table_data
+  let $sync_point= before_backup_data;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # inside write_table_data
+    # before initial phase
+    let $sync_point=before_backup_data_init;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+    # before prepare phase
+    let $sync_point=before_backup_data_prepare;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+    # before sync phase
+    let $sync_point=before_backup_data_lock;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+    # inside sync phase
+    let $sync_point=before_backup_data_unlock;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+    # after sync phase
+    let $sync_point=after_backup_binlog;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+    # before final phase
+    let $sync_point=before_backup_data_finish;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # before writing summary section
+  let $sync_point= before_backup_summary;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+# Note: after the call to do_backup() the operation is completed
+# and terminates successfully, even if interruption has happened 
+# after its completion.
+
+#
+# Test RESTORE interruptions.
+#
+
+--replace_column 1 #
+BACKUP DATABASE bup_intr TO 'bup_intr.bkp';
+DROP DATABASE bup_intr;
+
+let $do_restore=1;
+
+# before preparations
+let $sync_point= before_restore_prepare;
+--source suite/backup_engines/include/backup_restore_interrupt.inc
+
+# during preparations
+  # before logger initialization
+  let $sync_point= before_restore_logger_init;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+  
+  # before common preparations
+  let $sync_point= before_restore_common_prepare;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+  
+  # before openning the stream
+  let $sync_point= before_restore_stream_open;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # before creating catalogue
+  let $sync_point= before_restore_catalog;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # before reading header
+  let $sync_point= before_restore_read_header;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # before reading catalogue
+  let $sync_point= before_restore_read_catalog;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # before writing incident event
+  let $sync_point= before_restore_binlog;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+# before do_restore
+let $sync_point= after_backup_start_restore;
+--source suite/backup_engines/include/backup_restore_interrupt.inc
+
+# inside do_restore
+
+  # before disabling fkey constraints
+  let $sync_point= before_restore_fkey_disable;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # before reading metadata and creating objects
+  let $sync_point= before_restore_read_metadata;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+  # Note: now we pass the point when database is created during RESTORE,
+  # thus we need to DROP it before executing RESTORE another time.
+  DROP DATABASE bup_intr;
+
+  # before locking tables
+  let $sync_point= before_restore_lock_tables;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+  DROP DATABASE bup_intr;
+
+  # before restoring table data
+  let $sync_point= before_restore_table_data;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+  DROP DATABASE bup_intr;
+
+  # inside restore_table_data
+    # before creating restore drivers
+    let $sync_point= restore_before_drivers_create;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+    DROP DATABASE bup_intr;
+
+    # before initializing the drivers
+    let $sync_point= restore_before_drivers_init;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+    DROP DATABASE bup_intr;
+
+    # before reading table data chunk
+    let $sync_point= restore_before_read_data_chunk;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+    DROP DATABASE bup_intr;
+
+    # before sending the data to a driver
+    let $sync_point= restore_before_sending_data;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+    DROP DATABASE bup_intr;
+
+    # before shutting down the drivers
+    let $sync_point= restore_table_data_before_end;
+    --source suite/backup_engines/include/backup_restore_interrupt.inc
+    DROP DATABASE bup_intr;
+
+  # before restoring triggers
+  let $sync_point= before_restore_triggers;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+  DROP DATABASE bup_intr;
+
+  # before reading image summary block
+  let $sync_point= before_restore_read_summary;
+  --source suite/backup_engines/include/backup_restore_interrupt.inc
+
+
+#
+# Cleanup
+# 
+
+--disable_warnings
+DROP DATABASE IF EXISTS bup_intr;
+--error 0,1
+--remove_file $bdir/bup_intr.bkp
+--enable_warnings
+

=== modified file 'sql/backup/backup_kernel.h'
--- a/sql/backup/backup_kernel.h	2008-11-25 17:44:19 +0000
+++ b/sql/backup/backup_kernel.h	2008-12-08 12:13:32 +0000
@@ -207,8 +207,6 @@ void Backup_restore_ctx::disable_fkey_co
 inline
 int Backup_restore_ctx::fatal_error(int error_code)
 {
-  m_remove_loc= TRUE;
-
   if (m_error)
     return m_error;
 

=== modified file 'sql/backup/be_default.h'
--- a/sql/backup/be_default.h	2008-07-19 03:03:39 +0000
+++ b/sql/backup/be_default.h	2008-12-08 12:13:32 +0000
@@ -61,6 +61,7 @@ class Backup: public Backup_thread_drive
     { 
       mode= CANCEL;
       cleanup();
+      DBUG_EXECUTE_IF("backup_driver_cancel_error", return backup::ERROR;);
       return backup::OK;
     }
     TABLE_LIST *get_table_list() { return all_tables; }
@@ -135,6 +136,7 @@ class Restore: public Restore_driver
     { 
       mode= CANCEL;
       cleanup();
+      DBUG_EXECUTE_IF("backup_driver_cancel_error", return backup::ERROR;);
       return backup::OK;
     }
     void free() { delete this; };

=== modified file 'sql/backup/be_snapshot.h'
--- a/sql/backup/be_snapshot.h	2008-07-19 03:03:39 +0000
+++ b/sql/backup/be_snapshot.h	2008-12-08 12:13:32 +0000
@@ -46,6 +46,7 @@ class Backup: public default_backup::Bac
     { 
       m_cancel= TRUE;
       cleanup();
+      DBUG_EXECUTE_IF("backup_driver_cancel_error", return backup::ERROR;);
       return backup::OK;
     }
   private:

=== modified file 'sql/backup/be_thread.cc'
--- a/sql/backup/be_thread.cc	2008-10-30 12:29:54 +0000
+++ b/sql/backup/be_thread.cc	2008-12-08 12:13:32 +0000
@@ -241,6 +241,7 @@ end2:
   Constructor for Locking_thread_st structure.
 */
 Locking_thread_st::Locking_thread_st()
+ :m_thread_started(FALSE)
 {
   /*
     Initialize the thread mutex and cond variable.
@@ -260,13 +261,15 @@ Locking_thread_st::Locking_thread_st()
 Locking_thread_st::~Locking_thread_st()
 {
   /*
-    If the locking thread is not finished, we need to wait until
-    it is finished so that we can destroy the mutexes safely knowing
-    the locking thread won't access them.
+    If the locking thread has been started we need to kill it. We also need to 
+    wait until it dies before destroying the mutexes so that the locking thread 
+    won't access them any more.
   */
-  kill_locking_thread();
-  wait_until_locking_thread_dies();
-
+  if (m_thread_started)
+  {
+    kill_locking_thread();
+    wait_until_locking_thread_dies();
+  }
   /*
     Destroy the thread mutexes and cond variables.
   */
@@ -293,6 +296,7 @@ result_t Locking_thread_st::start_lockin
   if (pthread_create(&th, &connection_attrib,
                      backup_thread_for_locking, this))
     SET_STATE_TO_ERROR_AND_DBUG_RETURN;
+  m_thread_started= TRUE;
   DBUG_RETURN(backup::OK);
 }
 
@@ -306,6 +310,11 @@ result_t Locking_thread_st::start_lockin
 void Locking_thread_st::kill_locking_thread()
 {
   DBUG_ENTER("Locking_thread_st::kill_locking_thread");
+
+  // Nothing to do if the locking thread has not been started.
+  if (!m_thread_started)
+    DBUG_VOID_RETURN;
+
   pthread_mutex_lock(&THR_LOCK_caller);
   if (lock_state == LOCK_ERROR)
     THD_SET_PROC_INFO(m_thd, "error in the locking thread");
@@ -337,6 +346,10 @@ void Locking_thread_st::kill_locking_thr
 */
 void Locking_thread_st::wait_until_locking_thread_dies()
 {
+  // Nothing to do if the locking thread has not been started.
+  if (!m_thread_started)
+    return;
+
   pthread_mutex_lock(&THR_LOCK_caller);
   if (lock_state != LOCK_DONE)
   {
@@ -350,4 +363,6 @@ void Locking_thread_st::wait_until_locki
   }
   else
     pthread_mutex_unlock(&THR_LOCK_caller);
+
+  m_thread_started= FALSE;
 }

=== modified file 'sql/backup/be_thread.h'
--- a/sql/backup/be_thread.h	2008-07-09 07:12:43 +0000
+++ b/sql/backup/be_thread.h	2008-12-08 12:13:32 +0000
@@ -58,6 +58,8 @@ public:
   LOCK_STATE lock_state;           ///< Current state of the lock call
   THD *m_thd;                      ///< Pointer to current thread struct.
   String thd_name;                 ///< Name of locking thread
+  /// Indicates if the locking thread has been started.
+  my_bool m_thread_started;
 
   result_t start_locking_thread(const char *tname);
   void kill_locking_thread();

=== modified file 'sql/backup/data_backup.cc'
--- a/sql/backup/data_backup.cc	2008-11-26 10:05:19 +0000
+++ b/sql/backup/data_backup.cc	2008-12-08 12:13:32 +0000
@@ -510,7 +510,8 @@ int write_table_data(THD* thd, Backup_in
   List<Scheduler::Pump>  inactive;  // list of images not yet being created
 
   // keeps maximal init size for images in inactive list
-  size_t      max_init_size=0;
+  size_t  max_init_size=0;
+  bool    commits_blocked= FALSE;   // indicates if commit blocker is active
 
   DBUG_PRINT("backup_data",("initializing scheduler"));
 
@@ -524,13 +525,12 @@ int write_table_data(THD* thd, Backup_in
       continue;
 
     Scheduler::Pump *p= new Scheduler::Pump(*i, s);
-
     if (!p)
     {
       log.report_error(ER_OUT_OF_RESOURCES);
       goto error;
     }
-    if (!p->is_valid())
+    if (log.report_killed() || !p->is_valid())
     {
       log.report_error(ER_BACKUP_CREATE_BACKUP_DRIVER,p->m_name);
       delete p;
@@ -650,8 +650,9 @@ int write_table_data(THD* thd, Backup_in
       non-transactional tables and pass that to block_commits().
     */
     int error= 0;
-    error= block_commits(thd, NULL);
-    if (error)
+    if (!(error= block_commits(thd, NULL)))
+      commits_blocked= TRUE;
+    if (log.report_killed() || error)
       goto error;
 
     if (sch.prepare())    // logs errors
@@ -665,6 +666,12 @@ int write_table_data(THD* thd, Backup_in
     
     DBUG_PRINT("backup_data",("-- SYNC PHASE --"));
 
+    /*
+      Before proceeding, check if the process is interrupted.
+    */
+    if (log.report_killed())
+      goto error;
+
     log.report_state(BUP_VALIDITY_POINT);
     /*
       This breakpoint is used to assist in testing state changes for
@@ -678,13 +685,18 @@ int write_table_data(THD* thd, Backup_in
     */
 
     DEBUG_SYNC(thd, "before_backup_data_lock");
+    /*
+      Note: we do not detect/react to process interruptions during the 
+      synchronization. We let the protocol to go through and check for
+      possible interruptions only at the end, i.e., after sch.unlock().
+    */ 
     if (sch.lock())    // logs errors
       goto error;
 
     save_vp_info(info);
 
     DEBUG_SYNC(thd, "before_backup_data_unlock");
-    if (sch.unlock())    // logs errors
+    if (sch.unlock() || log.report_killed())    // logs errors
       goto error;
 
     /*
@@ -692,7 +704,8 @@ int write_table_data(THD* thd, Backup_in
     */
     DEBUG_SYNC(thd, "before_backup_unblock_commit");
     error= unblock_commits(thd);
-    if (error)
+    commits_blocked= FALSE;
+    if (log.report_killed() || error)
       goto error;
 
     report_vp_info(info);
@@ -719,6 +732,8 @@ int write_table_data(THD* thd, Backup_in
 
  error:
 
+  if (commits_blocked)
+    unblock_commits(thd);
   DBUG_RETURN(ERROR);
 }
 
@@ -769,10 +784,14 @@ class Scheduler::Pump_iterator
   Pick next backup pump and call its @c pump() method.
 
   Method updates statistics of number of drivers in each phase which is used
-  to detect end of a backup process.
+  to detect end of a backup process. A check for interruption is done each time
+  this method is called.
  */
 int Scheduler::step()
 {
+  if (m_log.report_killed())
+    return ER_QUERY_INTERRUPTED;
+
   // Pick next driver to pump data from.
 
   Pump_iterator p(*this);
@@ -885,7 +904,7 @@ int Scheduler::add(Pump *p)
   p->set_logger(&m_log);
   p->start_pos= avg;
 
-  if (p->begin())  // logs errors
+  if (p->begin() || m_log.report_killed())  // logs errors
   {
     delete p;
     return ERROR;
@@ -1004,7 +1023,7 @@ int Scheduler::prepare()
 
   for (Pump_iterator it(*this); it; ++it)
   {
-    if (it->prepare())  // logs errors
+    if (it->prepare() || m_log.report_killed())  // logs errors
     {
       remove_pump(it);  // Note: never errors.
       return ERROR;
@@ -1096,6 +1115,16 @@ Backup_pump::~Backup_pump()
   bitmap_free(&m_closed_streams);
 }
 
+/*
+  Note: The standard report_error() method does not log an error in case
+  the statement has been interrupted - the interruption is reported instead.
+  But we want to always report errors signalled by a backup driver, even if an
+  interruption has just happened. Therefore, inside Backup_pump methods where 
+  errors from the driver are reported, we use the variant of 
+  Logger::report_error() with explicit log_level::ERROR. This variant does not 
+  check for interruptions and always reports given error.
+*/ 
+
 /// Initialize backup driver.
 int Backup_pump::begin()
 {
@@ -1106,7 +1135,8 @@ int Backup_pump::begin()
   {
     state= backup_state::ERROR;
     if (m_log)
-      m_log->report_error(ER_BACKUP_INIT_BACKUP_DRIVER, m_name);
+      m_log->report_error(log_level::ERROR,
+                          ER_BACKUP_INIT_BACKUP_DRIVER, m_name);
     return ERROR;
   }
 
@@ -1124,7 +1154,8 @@ int Backup_pump::end()
     {
       state= backup_state::ERROR;
       if (m_log)
-        m_log->report_error(ER_BACKUP_STOP_BACKUP_DRIVER, m_name);
+        m_log->report_error(log_level::ERROR,
+                            ER_BACKUP_STOP_BACKUP_DRIVER, m_name);
       return ERROR;
     }
 
@@ -1153,7 +1184,8 @@ int Backup_pump::prepare()
   default:
     state= backup_state::ERROR;
     if (m_log)
-      m_log->report_error(ER_BACKUP_PREPARE_DRIVER, m_name);
+      m_log->report_error(log_level::ERROR,
+                          ER_BACKUP_PREPARE_DRIVER, m_name);
     return ERROR;
   }
 
@@ -1170,7 +1202,8 @@ int Backup_pump::lock()
   {
     state= backup_state::ERROR;
     if (m_log)
-      m_log->report_error(ER_BACKUP_CREATE_VP, m_name);
+      m_log->report_error(log_level::ERROR, 
+                          ER_BACKUP_CREATE_VP, m_name);
     return ERROR;
   }
 
@@ -1186,7 +1219,8 @@ int Backup_pump::unlock()
   {
     state= backup_state::ERROR;
     if (m_log)
-      m_log->report_error(ER_BACKUP_UNLOCK_DRIVER, m_name);
+      m_log->report_error(log_level::ERROR, 
+                          ER_BACKUP_UNLOCK_DRIVER, m_name);
     return ERROR;
   }
 
@@ -1199,7 +1233,8 @@ int Backup_pump::cancel()
   {
     state= backup_state::ERROR;
     if (m_log)
-      m_log->report_error(ER_BACKUP_CANCEL_BACKUP, m_name);
+      m_log->report_error(log_level::ERROR, 
+                          ER_BACKUP_CANCEL_BACKUP, m_name);
     return ERROR;
   }
   state= backup_state::CANCELLED;
@@ -1325,7 +1360,8 @@ int Backup_pump::pump(size_t *howmuch)
       case ERROR:
       default:
         if (m_log)
-          m_log->report_error(ER_BACKUP_GET_DATA, m_name);
+          m_log->report_error(log_level::ERROR,
+                              ER_BACKUP_GET_DATA, m_name);
         state= backup_state::ERROR;
         return ERROR;
 
@@ -1443,6 +1479,7 @@ int restore_table_data(THD *thd, Restore
   }
 
   // Create restore drivers
+  DEBUG_SYNC(thd, "restore_before_drivers_create");
   result_t res;
 
   for (uint n=0; n < info.snap_count(); ++n)
@@ -1456,6 +1493,8 @@ int restore_table_data(THD *thd, Restore
       continue;
 
     res= snap->get_restore_driver(drv[n]);
+    if (log.report_killed())
+      goto error;
     if (res == backup::ERROR)
     {
       log.report_error(ER_BACKUP_CREATE_RESTORE_DRIVER, snap->name());
@@ -1464,9 +1503,12 @@ int restore_table_data(THD *thd, Restore
  }
 
   // Initialize the drivers.
+  DEBUG_SYNC(thd, "restore_before_drivers_init");
   for (uint n=0; n < info.snap_count(); ++n)
   {
     res= drv[n]->begin(0);
+    if (log.report_killed())
+      goto error;
     if (res == backup::ERROR)
     {
       log.report_error(ER_BACKUP_INIT_RESTORE_DRIVER, info.m_snap[n]->name());
@@ -1497,9 +1539,13 @@ int restore_table_data(THD *thd, Restore
 
       case READING:
 
+        DEBUG_SYNC(thd, "restore_before_read_data_chunk");
         bzero(&chunk_info, sizeof(chunk_info));
         ret= bstream_rd_data_chunk(&s, &chunk_info);
 
+        if (log.report_killed())
+          goto error;
+
         switch (ret) {
 
         case BSTREAM_EOS:
@@ -1553,7 +1599,12 @@ int restore_table_data(THD *thd, Restore
          */
         DBUG_ASSERT(snap && drvr);
 
+        DEBUG_SYNC(thd, "restore_before_sending_data");
         ret= drvr->send_data(buf);
+
+        if (log.report_killed())
+          goto error;
+
         switch (ret) {
 
         case backup::OK:
@@ -1614,6 +1665,17 @@ int restore_table_data(THD *thd, Restore
     DBUG_PRINT("restore",("Shutting down restore driver %s",
                            info.m_snap[n]->name()));
     res= active[n]->end();
+    if (log.report_killed())
+    {
+      /* 
+        If ->end() call has failed we set active[n] to NULL as the driver is
+        no longer active and its ->cancel() method should not be called when 
+        we jump to error:
+      */
+      if (res == backup::ERROR)
+        active[n]= NULL; 
+      goto error;
+    }
     if (res == backup::ERROR)
     {
       state= ERROR;
@@ -1642,7 +1704,6 @@ error:
     DBUG_PRINT("restore",("Cancelling restore driver %s",
                            info.m_snap[n]->name()));
     res= active[n]->cancel();
-
     if (res)
     {
       if (!bad_drivers.is_empty())
@@ -1653,8 +1714,14 @@ error:
 
 finish:  
 
+  /*
+    We always log shutdown errors, even if an interruption has happened before.
+    This is why we must supply explicit log_level::ERROR to report_error() as
+    otherwise the method will report interruption instead of an error.
+  */
   if (!bad_drivers.is_empty())
-    log.report_error(ER_BACKUP_STOP_RESTORE_DRIVERS, bad_drivers.c_ptr());
+    log.report_error(log_level::ERROR, 
+                     ER_BACKUP_STOP_RESTORE_DRIVERS, bad_drivers.c_ptr());
 
   // Call free() for all existing drivers
 

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2008-11-28 10:10:39 +0000
+++ b/sql/backup/kernel.cc	2008-12-08 12:13:32 +0000
@@ -164,6 +164,7 @@ execute_backup_command(THD *thd, LEX *le
   {
     // prepare for backup operation
     
+    DEBUG_SYNC(thd, "before_backup_prepare");
     Backup_info *info= context.prepare_for_backup(backupdir, lex->backup_dir, 
                                                   thd->query,
                                                   lex->backup_compression);
@@ -194,8 +195,10 @@ execute_backup_command(THD *thd, LEX *le
 
     // perform backup
 
+    DEBUG_SYNC(thd, "before_do_backup");
     res= context.do_backup();
  
+    DEBUG_SYNC(thd, "after_do_backup");
     if (res)
       DBUG_RETURN(send_error(context, ER_BACKUP_BACKUP));
 
@@ -211,6 +214,7 @@ execute_backup_command(THD *thd, LEX *le
     if (obs::is_slave())
       DBUG_RETURN(send_error(context, ER_RESTORE_ON_SLAVE));
 
+    DEBUG_SYNC(thd, "before_restore_prepare");
     Restore_info *info= context.prepare_for_restore(backupdir, lex->backup_dir, 
                                                     thd->query);
     
@@ -238,7 +242,10 @@ execute_backup_command(THD *thd, LEX *le
 
   } // switch(lex->sql_command)
 
-  if (context.close())
+  res= context.close();
+  DEBUG_SYNC(thd, "backup_restore_done");
+
+  if (res)
     DBUG_RETURN(send_error(context, ER_BACKUP_CONTEXT_REMOVE));
 
   // All seems OK - send positive reply to client
@@ -387,12 +394,15 @@ Backup_restore_ctx::Backup_restore_ctx(T
     Check for progress tables.
   */
   MYSQL_BACKUP_LOG *backup_log= logger.get_backup_history_log_file_handler();
-  if (backup_log->check_backup_logs(thd))
+  if (report_killed())
+    m_error= ER_QUERY_INTERRUPTED;
+  else if (backup_log->check_backup_logs(thd))
     m_error= ER_BACKUP_PROGRESS_TABLES;
 }
 
 Backup_restore_ctx::~Backup_restore_ctx()
 {
+  DEBUG_SYNC(m_thd, "backup_restore_ctx_dtor");
   close();
 
   delete mem_alloc;
@@ -499,7 +509,10 @@ int Backup_restore_ctx::prepare(String *
     In case of error, we write only to backup logs, because check_global_access()
     pushes the same error on the error stack.
   */
+  DEBUG_SYNC(m_thd, "before_backup_privileges");
   ret= check_global_access(m_thd, SUPER_ACL);
+  if (report_killed())
+    return fatal_error(ER_QUERY_INTERRUPTED);
   if (ret)
     return fatal_error(log_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, "SUPER"));
 
@@ -508,6 +521,7 @@ int Backup_restore_ctx::prepare(String *
     this operation.
    */
 
+  DEBUG_SYNC(m_thd, "before_backup_single_op");
   pthread_mutex_lock(&run_lock);
 
   if (!current_op)
@@ -542,6 +556,8 @@ int Backup_restore_ctx::prepare(String *
 
 #endif
 
+  if (report_killed())
+    return fatal_error(ER_QUERY_INTERRUPTED);
   if (bad_filename)
     return fatal_error(report_error(ER_BAD_PATH, location.str));
 
@@ -562,7 +578,10 @@ int Backup_restore_ctx::prepare(String *
 
   // Freeze all meta-data. 
 
+  DEBUG_SYNC(m_thd, "before_backup_ddl_block");
   ret= obs::ddl_blocker_enable(m_thd);
+  if (report_killed())
+    return fatal_error(ER_QUERY_INTERRUPTED);
   if (ret)
     return fatal_error(report_error(ER_DDL_BLOCK));
 
@@ -597,8 +616,15 @@ Backup_restore_ctx::prepare_for_backup(S
   
   if (m_error)
     return NULL;
-  
-  if (Logger::init(BACKUP, query))      // Logs errors
+
+  DEBUG_SYNC(m_thd, "before_backup_logger_init");
+  int ret= Logger::init(BACKUP, query);  // Logs errors   
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
+  if (ret)
   {
     fatal_error(ER_BACKUP_LOGGER_INIT);
     return NULL;
@@ -611,7 +637,8 @@ Backup_restore_ctx::prepare_for_backup(S
     Do preparations common to backup and restore operations. After call
     to prepare() all meta-data changes are blocked.
    */ 
-  if (prepare(backupdir, orig_loc))
+  DEBUG_SYNC(m_thd, "before_backup_common_prepare");
+  if (prepare(backupdir, orig_loc))  // Logs errors and detects interruptions
     return NULL;
 
   /*
@@ -622,16 +649,32 @@ Backup_restore_ctx::prepare_for_backup(S
                                       with_compression);
   m_stream= s;
   
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
   if (!s)
   {
     fatal_error(report_error(ER_OUT_OF_RESOURCES));
     return NULL;
   }
 
-  // Mark that the file should be removed unless operation completes successfuly
-  m_remove_loc= TRUE;
-
+  DEBUG_SYNC(m_thd, "before_backup_stream_open");
   int my_open_status= s->open();
+
+  /* 
+    If we managed to successfully open the output location (i.e., the output 
+    file) for writing, mark it for removal in case operation is aborted.
+    When BACKUP completes, m_remove_loc will be set to FALSE.
+  */
+  m_remove_loc= (my_open_status == 0);
+
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
   if (my_open_status != 0)
   {
     report_stream_open_failure(my_open_status, &orig_loc);
@@ -642,14 +685,20 @@ Backup_restore_ctx::prepare_for_backup(S
     Create backup catalogue.
    */
 
+  DEBUG_SYNC(m_thd, "before_backup_catalog");
   Backup_info *info= new Backup_info(*this, m_thd);    // Logs errors
+  m_catalog= info;
 
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
   if (!info)
   {
     fatal_error(report_error(ER_OUT_OF_RESOURCES));
     return NULL;
   }
-
   if (!info->is_valid())
   {
     // Error has been logged by Backup_info constructor
@@ -673,7 +722,6 @@ Backup_restore_ctx::prepare_for_backup(S
     info->flags|= BSTREAM_FLAG_BINLOG; 
 
   info->save_start_time(when);
-  m_catalog= info;
   m_state= PREPARED_FOR_BACKUP;
   
   return info;
@@ -701,7 +749,14 @@ Backup_restore_ctx::prepare_for_restore(
   if (m_error)
     return NULL;
   
-  if (Logger::init(RESTORE, query))
+  DEBUG_SYNC(m_thd, "before_restore_logger_init");
+  int ret= Logger::init(RESTORE, query);  // Logs errors
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
+  if (ret)
   {
     fatal_error(ER_BACKUP_LOGGER_INIT);
     return NULL;
@@ -714,6 +769,7 @@ Backup_restore_ctx::prepare_for_restore(
     Do preparations common to backup and restore operations. After this call
     changes of meta-data are blocked.
    */ 
+  DEBUG_SYNC(m_thd, "before_restore_common_prepare");
   if (prepare(backupdir, orig_loc))
     return NULL;
   
@@ -724,13 +780,24 @@ Backup_restore_ctx::prepare_for_restore(
   Input_stream *s= new Input_stream(*this, &m_path);
   m_stream= s;
   
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
   if (!s)
   {
     fatal_error(report_error(ER_OUT_OF_RESOURCES));
     return NULL;
   }
   
+  DEBUG_SYNC(m_thd, "before_restore_stream_open");
   int my_open_status= s->open();
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
   if (my_open_status != 0)
   {
     report_stream_open_failure(my_open_status, &orig_loc);
@@ -741,14 +808,20 @@ Backup_restore_ctx::prepare_for_restore(
     Create restore catalogue.
    */
 
+  DEBUG_SYNC(m_thd, "before_restore_catalog");
   Restore_info *info= new Restore_info(*this, m_thd);  // reports errors
+  m_catalog= info;
 
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
   if (!info)
   {
     fatal_error(report_error(ER_OUT_OF_RESOURCES));
     return NULL;
   }
-
   if (!info->is_valid())
   {
     // Errors are logged by Restore_info constructor. 
@@ -757,15 +830,18 @@ Backup_restore_ctx::prepare_for_restore(
   }
 
   info->save_start_time(when);
-  m_catalog= info;
-
-  int ret;
 
   /*
     Read header and catalogue from the input stream.
    */
 
+  DEBUG_SYNC(m_thd, "before_restore_read_header");
   ret= read_header(*info, *s);  // Can log errors via callback functions.
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
   if (ret)
   {
     if (!error_reported())
@@ -780,7 +856,13 @@ Backup_restore_ctx::prepare_for_restore(
     return NULL;
   }
 
+  DEBUG_SYNC(m_thd, "before_restore_read_catalog");
   ret= read_catalog(*info, *s);  // Can log errors via callback functions.
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
   if (ret)
   {
     if (!error_reported())
@@ -797,6 +879,7 @@ Backup_restore_ctx::prepare_for_restore(
 
   m_state= PREPARED_FOR_RESTORE;
 
+  DEBUG_SYNC(m_thd, "before_restore_binlog");
   /*
     Do not allow slaves to connect during a restore.
 
@@ -816,6 +899,11 @@ Backup_restore_ctx::prepare_for_restore(
     obs::engage_binlog(FALSE);
   }
 
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    return NULL;
+  }
   return info;
 }
 
@@ -881,6 +969,8 @@ int Backup_restore_ctx::lock_tables_for_
                                     MYSQL_OPEN_SKIP_TEMPORARY 
                                           /* do not open tmp tables */
                                    );
+  if (report_killed())
+    return fatal_error(ER_QUERY_INTERRUPTED);
   if (ret)
     return fatal_error(report_error(ER_BACKUP_OPEN_TABLES,"RESTORE"));
 
@@ -923,6 +1013,15 @@ int Backup_restore_ctx::close()
   if (m_state == CLOSED)
     return 0;
 
+  /*
+    Note: The standard report_error() method does not log an error in case
+    the statement has been interrupted - the interruption is reported instead.
+    But we want to always report errors which happen during shutdown phase.
+    Therefore, for reporting errors here we use the variant of 
+    Logger::report_error() with explicit log_level::ERROR. This variant does not 
+    check for interruptions and always reports given error.
+  */ 
+
   using namespace backup;
 
   /*
@@ -953,7 +1052,7 @@ int Backup_restore_ctx::close()
   if (m_stream && !m_stream->close())
   {
     // Note error, but complete clean-up
-    fatal_error(report_error(ER_BACKUP_CLOSE));
+    fatal_error(report_error(log_level::ERROR, ER_BACKUP_CLOSE));
   }
 
   if (m_catalog)
@@ -965,27 +1064,23 @@ int Backup_restore_ctx::close()
     Important: This is done only for backup operation - RESTORE should never
     remove the specified backup image!
    */
-  if (m_remove_loc && m_state == PREPARED_FOR_BACKUP)
+  if (m_remove_loc && Logger::m_type == Logger::BACKUP)
   {
     int ret= my_delete(m_path.c_ptr(), MYF(0));
-
+    DBUG_EXECUTE_IF("backup_remove_location_error", ret= TRUE;);
     /*
       Ignore ENOENT error since it is ok if the file doesn't exist.
      */
     if (ret && my_errno != ENOENT)
-      fatal_error(report_error(ER_CANT_DELETE_FILE, m_path.c_ptr(), my_errno));
+      fatal_error(report_error(log_level::ERROR, ER_CANT_DELETE_FILE, 
+                               m_path.c_ptr(), my_errno));
   }
 
-  /* We report completion of the operation only if no errors were detected,
-     and logger has been initialized.
+  /* 
+    Call report_stop(), but do it only if report_start() has been called before.
   */
-  if (!m_error)
-  {
-    if (backup::Logger::m_state == backup::Logger::RUNNING)
-    {
-      report_stop(when, TRUE);
-    }
-  }
+  if (backup::Logger::m_state == backup::Logger::RUNNING)
+    report_stop(when, !m_error /* is it successful completion? */);
 
   /* 
     Destroy backup stream's memory allocator (this frees memory)
@@ -1037,10 +1132,15 @@ int Backup_restore_ctx::do_backup()
 
   report_stats_pre(info);                       // Never errors
 
+  if (report_killed())
+    DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
+
   DBUG_PRINT("backup",("Writing preamble"));
   DEBUG_SYNC(m_thd, "backup_before_write_preamble");
 
   ret= write_preamble(info, s);  // Can Log errors via callback functions.
+  if (report_killed())
+    DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
   if (ret)
   {
     if (!error_reported())
@@ -1052,13 +1152,16 @@ int Backup_restore_ctx::do_backup()
 
   DEBUG_SYNC(m_thd, "before_backup_data");
 
-  ret= write_table_data(m_thd, info, s); // logs errors
+  ret= write_table_data(m_thd, info, s); // logs errors and detects interruptions
   if (ret)
     DBUG_RETURN(fatal_error(ret));
 
   DBUG_PRINT("backup",("Writing summary"));
 
+  DEBUG_SYNC(m_thd, "before_backup_summary");
   ret= write_summary(info, s);  
+  if (report_killed())
+    DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
   if (ret)
     DBUG_RETURN(fatal_error(report_error(ER_BACKUP_WRITE_SUMMARY)));
 
@@ -1100,21 +1203,37 @@ int Backup_restore_ctx::restore_triggers
   Image_info::Obj *obj;
   List<Image_info::Obj> events;
   Image_info::Obj::describe_buf buf;
-
+  // Note: The two iterators below must be deleted upon exit.
+  Image_info::Iterator *trgit= NULL;
   Image_info::Iterator *dbit= m_catalog->get_dbs();
+  if (report_killed())
+  {
+    fatal_error(ER_QUERY_INTERRUPTED);
+    goto exit;
+  }
   if (!dbit)
-    DBUG_RETURN(fatal_error(report_error(ER_OUT_OF_RESOURCES)));
+  {
+    fatal_error(report_error(ER_OUT_OF_RESOURCES));
+    goto exit;
+  }
 
   // create all trigers and collect events in the events list
   
   while ((obj= (*dbit)++)) 
   {
-    Image_info::Iterator *it=
-                    m_catalog->get_db_objects(*static_cast<Image_info::Db*>(obj));
-    if (!it)
-      DBUG_RETURN(fatal_error(report_error(ER_OUT_OF_RESOURCES)));
+    trgit= m_catalog->get_db_objects(*static_cast<Image_info::Db*>(obj));
+    if (report_killed())
+    {
+      fatal_error(ER_QUERY_INTERRUPTED);
+      goto exit;
+    }
+    if (!trgit)
+    {
+      fatal_error(report_error(ER_OUT_OF_RESOURCES));
+      goto exit;
+    }
 
-    while ((obj= (*it)++))
+    while ((obj= (*trgit)++))
       switch (obj->type()) {
       
       case BSTREAM_IT_EVENT:
@@ -1122,7 +1241,8 @@ int Backup_restore_ctx::restore_triggers
         if (events.push_back(obj))
         {
           // Error has been reported, but not logged to backup logs
-          DBUG_RETURN(fatal_error(log_error(ER_OUT_OF_RESOURCES))); 
+          fatal_error(log_error(ER_OUT_OF_RESOURCES));
+          goto exit; 
         }
         break;
       
@@ -1130,35 +1250,58 @@ int Backup_restore_ctx::restore_triggers
         DBUG_ASSERT(obj->m_obj_ptr);
         if (obj->m_obj_ptr->execute(m_thd))
         {
-          delete it;
-          delete dbit;
-          int err= report_error(ER_BACKUP_CANT_RESTORE_TRIGGER,
-                                obj->describe(buf));
-          DBUG_RETURN(fatal_error(err));
+          fatal_error(report_error(ER_BACKUP_CANT_RESTORE_TRIGGER,
+                                   obj->describe(buf)));
+          goto exit;
         }
         break;
 
       default: break;      
       }
 
-    delete it;
+    delete trgit;
+    trgit= NULL;
   }
 
   delete dbit;
+  dbit= NULL;
 
   // now create all events
+  
+  {
+    List_iterator<Image_info::Obj> it(events);
+    Image_info::Obj *ev;
 
-  List_iterator<Image_info::Obj> it(events);
-  Image_info::Obj *ev;
-
-  while ((ev= it++)) 
-    if (ev->m_obj_ptr->execute(m_thd))
+    while ((ev= it++))
     {
-      int ret= report_error(ER_BACKUP_CANT_RESTORE_EVENT,ev->describe(buf));
-      DBUG_RETURN(fatal_error(ret));
-    };
+      int ret= ev->m_obj_ptr->execute(m_thd); 
+      if (report_killed())
+      {
+        fatal_error(ER_QUERY_INTERRUPTED);
+        goto exit;
+      }
+      if (ret)
+      {
+        fatal_error(report_error(ER_BACKUP_CANT_RESTORE_EVENT,ev->describe(buf)));
+        goto exit;
+      }
+    }
+  }
 
-  DBUG_RETURN(0);
+  /* 
+    FIXME: this call is here because object services doesn't clean the
+    statement execution context properly, which leads to assertion failure.
+    It should be fixed inside object services implementation and then the
+    following line should be removed (see BUG#41294).
+   */
+  close_thread_tables(m_thd);                   // Never errors
+  m_thd->main_da.reset_diagnostics_area();      // Never errors
+
+exit:
+
+  delete dbit;
+  delete trgit;
+  DBUG_RETURN(m_error);
 }
 
 /**
@@ -1191,6 +1334,9 @@ int Backup_restore_ctx::do_restore(bool 
 
   report_stats_pre(info);                       // Never errors
 
+  if (report_killed())
+    DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
+
   DBUG_PRINT("restore", ("Restoring meta-data"));
 
   // unless RESTORE... OVERWRITE: return error if database already exists
@@ -1204,7 +1350,10 @@ int Backup_restore_ctx::do_restore(bool 
     Image_info::Db *mydb;
     while ((mydb= static_cast<Image_info::Db*>((*dbit)++)))
     {
-      if (!obs::check_db_existence(&mydb->name())) 
+      err= obs::check_db_existence(&mydb->name());
+      if (report_killed())
+        DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
+      if (!err) 
       {
         delete dbit;
         err= report_error(ER_RESTORE_DB_EXISTS, mydb->name().ptr());
@@ -1214,9 +1363,16 @@ int Backup_restore_ctx::do_restore(bool 
     delete dbit;
   }
 
+  DEBUG_SYNC(m_thd, "before_restore_fkey_disable");
   disable_fkey_constraints();                   // Never errors
 
-  err= read_meta_data(info, s);  // Can log errors via callback functions.
+  if (report_killed())
+    DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
+
+  DEBUG_SYNC(m_thd, "before_restore_read_metadata");
+  err= read_meta_data(m_thd, info, s); // Can log errors via callback functions.
+  if (report_killed())
+    DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
   if (err)
   {
     if (!error_reported())
@@ -1231,24 +1387,23 @@ int Backup_restore_ctx::do_restore(bool 
 
   DBUG_PRINT("restore",("Restoring table data"));
 
-  /* 
-    FIXME: this call is here because object services doesn't clean the
-    statement execution context properly, which leads to assertion failure.
-    It should be fixed inside object services implementation and then the
-    following line should be removed.
-   */
-  close_thread_tables(m_thd);                   // Never errors
-  m_thd->main_da.reset_diagnostics_area();      // Never errors  
-
+  DEBUG_SYNC(m_thd, "before_restore_lock_tables");
   err= lock_tables_for_restore();               // logs errors
+  if (report_killed())
+    DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
   if (err)
     DBUG_RETURN(fatal_error(err));
 
-  // Here restore drivers are created to restore table data
-  err= restore_table_data(m_thd, info, s);      // logs errors
+  /* 
+    Here restore drivers are created to restore table data. Function 
+    restore_table_data() logs errors and detects interruptions.
+   */
+  DEBUG_SYNC(m_thd, "before_restore_table_data");
+  err= restore_table_data(m_thd, info, s);
 
   unlock_tables();                              // Never errors
-
+  if (report_killed())
+    DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
   if (err)
     DBUG_RETURN(fatal_error(err));
 
@@ -1259,22 +1414,17 @@ int Backup_restore_ctx::do_restore(bool 
    creation of these objects will fail.
   */
 
-  err= restore_triggers_and_events();           // logs errors
+  DEBUG_SYNC(m_thd, "before_restore_triggers");
+  err= restore_triggers_and_events();   // logs errors and detects interruptions
   if (err)
      DBUG_RETURN(fatal_error(err));
 
-  /* 
-    FIXME: this call is here because object services doesn't clean the
-    statement execution context properly, which leads to assertion failure.
-    It should be fixed inside object services implementation and then the
-    following line should be removed.
-   */
-  close_thread_tables(m_thd);                   // Never errors
-  m_thd->main_da.reset_diagnostics_area();      // Never errors
-
   DBUG_PRINT("restore",("Done."));
 
+  DEBUG_SYNC(m_thd, "before_restore_read_summary");
   err= read_summary(info, s);
+  if (report_killed())
+    DBUG_RETURN(fatal_error(ER_QUERY_INTERRUPTED));
   if (err)
     DBUG_RETURN(fatal_error(report_error(ER_BACKUP_READ_SUMMARY)));
 
@@ -1988,7 +2138,7 @@ int bcat_create_item(st_bstream_image_he
     */
     if (!obs::check_user_existence(thd, sobj->get_name()))
     {
-      log.report_error(log_level::WARNING, 
+      log.report_error(log_level::WARNING,
                        ER_BACKUP_GRANT_SKIPPED, 
                        create_stmt);
       return BSTREAM_OK; 

=== modified file 'sql/backup/logger.cc'
--- a/sql/backup/logger.cc	2008-11-28 10:10:39 +0000
+++ b/sql/backup/logger.cc	2008-12-08 12:13:32 +0000
@@ -155,6 +155,7 @@ void Logger::report_stats_pre(const Imag
 {
   DBUG_ASSERT(m_state == RUNNING);
   backup_log->num_objects(info.table_count());
+
   // Compose list of databases.
 
   Image_info::Db_iterator *it= info.get_dbs();
@@ -221,4 +222,49 @@ bool Logger::push_errors(bool flag)
   return old;
 } 
 
+/**
+  Report the fact that BACKUP/RESTORE operation has been cancelled.
+
+  This method does nothing if no interruption has happened or if an 
+  interruption has already been reported. Otherwise it logs
+  ER_BACKUP_INTERRUPTED note.
+
+  @note The server takes care of giving feedback to the client in case of a 
+  cancelled statement - nothing needs to be done here (nothing pushed on the 
+  server's error stack)
+
+  @returns TRUE if interruption has been detected and reported, 
+  FALSE otherwise.
+ */ 
+bool Logger::report_killed()
+{
+  if (!m_thd->killed)
+    return FALSE;
+
+  if (m_kill_reported)
+    return TRUE;
+
+  m_thd->send_kill_message();
+  m_error_reported= TRUE;
+
+  if (m_state == CREATED || m_state == READY)
+    return TRUE;
+
+  // log_error() does not push messages on the server's error stack.
+  log_error(backup::log_level::INFO, ER_BACKUP_INTERRUPTED);  
+
+  /*
+    Note: It is not possible to open online backup log tables if current
+    query has been killed (m_thd->killed is non-zero). Thus in that case 
+    we can't update state accordingly. This is a limitation of the current 
+    implementation of the online backup logging mechanism.
+  */ 
+  if (m_state == RUNNING)
+    report_state(BUP_CANCEL);
+
+  m_kill_reported= TRUE;
+
+  return TRUE;
+}
+
 } // backup namespace

=== modified file 'sql/backup/logger.h'
--- a/sql/backup/logger.h	2008-11-25 17:44:19 +0000
+++ b/sql/backup/logger.h	2008-12-08 12:13:32 +0000
@@ -52,6 +52,7 @@ class Logger
    int report_error(const char *format, ...);
    int write_message(log_level::value level, const char *msg, ...);
    int log_error(int error_code, ...);
+   int log_error(log_level::value level, int error_code, ...);
 
    void report_start(time_t);
    void report_stop(time_t, bool);
@@ -63,6 +64,8 @@ class Logger
    void report_backup_file(char * path);
    void report_stats_pre(const Image_info&);
    void report_stats_post(const Image_info&);
+   bool report_killed();
+
    ulonglong get_op_id() const 
    {
      DBUG_ASSERT(backup_log);
@@ -89,6 +92,8 @@ class Logger
 
   bool m_push_errors;        ///< Should errors be pushed on warning stack?
   bool m_error_reported;     ///< Has any error been reported?
+  /// Flag preventing double reporting of process interruption.
+  bool m_kill_reported;
 
   Backup_log *backup_log;    ///< Backup log interface class.
 };
@@ -96,7 +101,7 @@ class Logger
 inline
 Logger::Logger(THD *thd) 
    :m_type(BACKUP), m_state(CREATED), m_thd(thd), m_push_errors(TRUE), 
-    m_error_reported(FALSE), backup_log(0)
+    m_error_reported(FALSE), m_kill_reported(FALSE), backup_log(0)
 {}
 
 inline
@@ -118,10 +123,18 @@ int Logger::write_message(log_level::val
   return res;
 }
 
-/// Reports error with log_level::ERROR.
+/** 
+  Reports error with log_level::ERROR.
+
+  Before reporting error, this method checks for interruption. In case there 
+  was one, the interruption is reported instead.
+*/
 inline
 int Logger::report_error(int error_code, ...)
 {
+  if (report_killed())
+    return ER_QUERY_INTERRUPTED;
+
   va_list args;
 
   va_start(args, error_code);
@@ -144,10 +157,21 @@ int Logger::report_error(log_level::valu
   return res;
 }
 
-/// Reports error with given description.
+/** 
+  Reports given message with log_level::ERROR.
+
+  This method can be used for reporting errors which are not registered in 
+  errmsg.txt.
+
+  Before reporting the message, this method checks for interruption. In case 
+  there was one, the interruption is reported instead.
+*/
 inline
 int Logger::report_error(const char *format, ...)
 {
+  if (report_killed())
+    return ER_QUERY_INTERRUPTED;
+
   va_list args;
 
   va_start(args, format);
@@ -157,10 +181,18 @@ int Logger::report_error(const char *for
   return res;
 }
 
-/// Reports error without pushing it on server's error stack.
+/** 
+  Reports error with log_level::ERROR without pushing it on error stack. 
+
+  Before reporting the error, this method checks for interruption. In case 
+  there was one, the interruption is reported instead.
+*/
 inline
 int Logger::log_error(int error_code, ...)
 {
+  if (report_killed())
+    return ER_QUERY_INTERRUPTED;
+
   va_list args;
   bool    saved= push_errors(FALSE);
   
@@ -173,6 +205,22 @@ int Logger::log_error(int error_code, ..
   return res;
 }
 
+/** 
+  Reports error on the given log_level, without pushing it on server's 
+  error stack.
+*/
+inline
+int Logger::log_error(log_level::value level, int error_code, ...)
+{
+  va_list args;
+
+  va_start(args, error_code);
+  int res= v_report_error(level, error_code, args);
+  va_end(args);
+
+  return res;
+}
+
 /// Report start of an operation.
 inline
 void Logger::report_start(time_t when)

=== modified file 'sql/backup/stream.cc'
--- a/sql/backup/stream.cc	2008-10-15 20:00:48 +0000
+++ b/sql/backup/stream.cc	2008-12-08 12:13:32 +0000
@@ -249,6 +249,8 @@ int Stream::open()
 bool Stream::close()
 {
   bool ret= TRUE;
+
+  DBUG_EXECUTE_IF("backup_stream_close_error", { m_fd=-1; return FALSE; });
   if (m_fd >= 0)
   {
     if (my_close(m_fd, MYF(0)))

=== modified file 'sql/backup/stream.h'
--- a/sql/backup/stream.h	2008-11-13 13:02:36 +0000
+++ b/sql/backup/stream.h	2008-12-08 12:13:32 +0000
@@ -192,11 +192,29 @@ read_catalog(Image_info &info, Input_str
   return ret == BSTREAM_ERROR ? ERROR : OK;
 }
 
+/*
+  FIXME: the thd parameter for read_meta_data() is here only because the
+  temporary code within the function needs it. It should be removed once the
+  issue is fixed (see BUG#41294).
+*/ 
 inline
 result_t
-read_meta_data(Image_info &info, Input_stream &s)
+read_meta_data(THD *thd, Image_info &info, Input_stream &s)
 {
   int ret= bstream_rd_meta_data(&s, static_cast<st_bstream_image_header*>(&info));
+
+  /* 
+    FIXME: the following code is here because object services doesn't clean the
+    statement execution context properly, which leads to assertion failure.
+    It should be fixed inside object services implementation and then the
+    following line should be removed (see BUG#41294).
+   */
+  DBUG_ASSERT(thd);
+  close_thread_tables(thd);                   // Never errors
+  if (ret != BSTREAM_ERROR)
+    thd->main_da.reset_diagnostics_area();    // Never errors  
+  /* end of temporary code */
+
   return ret == BSTREAM_ERROR ? ERROR : OK;
 }
 

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2008-11-28 10:10:39 +0000
+++ b/sql/share/errmsg.txt	2008-12-08 12:13:32 +0000
@@ -6238,7 +6238,7 @@ ER_BACKUP_INIT_RESTORE_DRIVER
 ER_BACKUP_STOP_BACKUP_DRIVER
         eng "Can't shut down %-.64s backup driver"
 ER_BACKUP_STOP_RESTORE_DRIVERS
-        eng "Can't shut down %-.64s backup driver(s)"
+        eng "Can't shut down %-.64s restore driver(s)"
 ER_BACKUP_PREPARE_DRIVER
         eng "%-.64s backup driver can't prepare for synchronization"
 ER_BACKUP_CREATE_VP
@@ -6442,3 +6442,5 @@ ER_BACKUP_BACKUP_DBS
   eng "Backing up %u database(s) %.220s"
 ER_BACKUP_RESTORE_DBS
   eng "Restoring %u database(s) %.220s"
+ER_BACKUP_INTERRUPTED
+  eng "Operation has been interrupted."

Thread
bzr commit into mysql-6.0-backup branch (Rafal.Somla:2740) Bug#35079 WL#4538Rafal Somla8 Dec