Bug #46575 Backup fails to return ER_BACKUP_FAILED_TO_INIT_COMPRESSION
Submitted: 5 Aug 2009 20:23 Modified: 7 Aug 2009 14:52
Reporter: Chuck Bell Email Updates:
Status: Can't repeat Impact on me:
None 
Category:MySQL Server: Backup Severity:S3 (Non-critical)
Version:5.4.4 OS:Any
Assigned to: Jørgen Løland CPU Architecture:Any

[5 Aug 2009 20:23] Chuck Bell
Description:
The code in data_backup.cc is designed to return an error if there is a problem opening a stream using compression. See line #486 in stream.cc.

If you use debug insertion (see below), the server will crash. The problem appears in deflate.cc @ line#565. Note that this is after the error has been handled by the debug insertion test (see below) and appears to be during cleanup.

How to repeat:
The crash can be reproduced using this patch:

=== modified file 'sql/backup/stream.cc'
--- sql/backup/stream.cc        2009-05-19 20:20:54 +0000
+++ sql/backup/stream.cc        2009-08-05 18:18:31 +0000
@@ -486,6 +486,13 @@ int Output_stream::open()
     zstream.msg= 0;
     zstream.next_out= zbuf;
     zstream.avail_out= ZBUF_SIZE;
+
+    // Debug insertion for ER_BACKUP_FAILED_TO_INIT_COMPRESSION.
+    DBUG_EXECUTE_IF("ER_BACKUP_FAILED_TO_INIT_COMPRESSION",
+      m_log.report_error(ER_BACKUP_FAILED_TO_INIT_COMPRESSION,
+                         0, "Debug insertion test");
+      return ER_BACKUP_WRITE_LOC;);
+
     if ((zerr= deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
                             MAX_WBITS + 16, MAX_MEM_LEVEL,
                             Z_DEFAULT_STRATEGY) != Z_OK))

And this test:

--echo #
--echo # Create database and data to test.
--echo #
CREATE DATABASE backup_test;
CREATE TABLE backup_test.t1 (a char(30)) ENGINE=MEMORY;
INSERT INTO backup_test.t1 VALUES ("01 Test Basic database example"); 
INSERT INTO backup_test.t1 VALUES ("02 Test Basic database example"); 
INSERT INTO backup_test.t1 VALUES ("03 Test Basic database example"); 
INSERT INTO backup_test.t1 VALUES ("04 Test Basic database example"); 
INSERT INTO backup_test.t1 VALUES ("05 Test Basic database example"); 
INSERT INTO backup_test.t1 VALUES ("06 Test Basic database example"); 
INSERT INTO backup_test.t1 VALUES ("07 Test Basic database example"); 

CREATE TABLE backup_test.t2 (a char(30)) ENGINE=MEMORY;
INSERT INTO backup_test.t2 VALUES ("11 Test Basic database example"); 
INSERT INTO backup_test.t2 VALUES ("12 Test Basic database example"); 
INSERT INTO backup_test.t2 VALUES ("13 Test Basic database example"); 

--echo #
--echo # Now create more database objects for test.
--echo #
CREATE PROCEDURE backup_test.p1(p1 CHAR(20))
  INSERT INTO backup_test.t1 VALUES ("50");

CREATE TRIGGER backup_test.trg AFTER INSERT ON backup_test.t1 FOR EACH ROW
 INSERT INTO backup_test.t1 VALUES('Test objects count');

CREATE FUNCTION backup_test.f1() RETURNS INT RETURN (SELECT 1);

CREATE VIEW backup_test.v1 as SELECT * FROM backup_test.t1;

CREATE EVENT backup_test.e1 ON SCHEDULE EVERY 1 YEAR DO
  DELETE FROM backup_test.t1 WHERE a = "not there";

--echo #
--echo # Now we need some privileges
--echo #
GRANT ALL ON backup_test.* TO 'joe'@'user';

BACKUP DATABASE backup_test TO 'orig.bak';

SET SESSION debug="+d,ER_BACKUP_FAILED_TO_INIT_COMPRESSION";
--replace_column 1 #
BACKUP DATABASE backup_test TO '1.bak' WITH COMPRESSION;
SET SESSION debug="-d";

RESTORE FROM 'orig.bak';

Suggested fix:
Unknown.

Note: once this is fixed, the test case can be enabled in backup_errors_debug_1.test using this test case:

# Test for error ER_BACKUP_FAILED_TO_INIT_COMPRESSION.
LET $caseno = 15;
LET $errno = $ER_BACKUP_FAILED_TO_INIT_COMPRESSION;
LET $errname = ER_BACKUP_FAILED_TO_INIT_COMPRESSION;
LET $operation = BACKUP;
LET $compress = ON;
--source suite/backup/include/test_for_error.inc
LET $compress = OFF;
[6 Aug 2009 19:36] Chuck Bell
Hehehe...alternative spelling for 'fails' :)
[7 Aug 2009 14:52] Chuck Bell
Using the latest code from the team tree and the alternative error code insertion technique of:

    ret= (zerr= deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
                            MAX_WBITS + 16, MAX_MEM_LEVEL,
                            Z_DEFAULT_STRATEGY) != Z_OK);

    // Error code insertion for ER_BACKUP_FAILED_TO_INIT_COMPRESSION.
    DBUG_EXECUTE_IF("ER_BACKUP_FAILED_TO_INIT_COMPRESSION", ret= 1;);

    if (ret)
    {
      m_log.report_error(ER_BACKUP_FAILED_TO_INIT_COMPRESSION,
                         zerr, zstream.msg);
      return ER_BACKUP_WRITE_LOC;
    }

The problem is not repeatable.