SQLite

Check-in [231b588022]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a segfault that could occur following an OOM condition in the concurrent transaction code.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | begin-concurrent
Files: files | file ages | folders
SHA1: 231b5880228cf01efe3981bc8be3150d79b422e5
User & Date: dan 2015-08-25 14:37:39.823
Context
2015-08-25
16:01
Test that if a corrupt wal-index header is encountered when attempting to commit a concurrent transaction, SQLITE_BUSY_SNAPSHOT is returned to the caller. (check-in: c746e0bd20 user: dan tags: begin-concurrent)
14:37
Fix a segfault that could occur following an OOM condition in the concurrent transaction code. (check-in: 231b588022 user: dan tags: begin-concurrent)
11:16
Merge latest trunk changes with this branch. (check-in: 3e7d6dd62d user: dan tags: begin-concurrent)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909

3910
3911
3912
3913
3914
3915
3916
      iNew = ++(*pnCurrent);
      if( iNew==PENDING_BYTE_PAGE(pBt) ) iNew = ++(*pnCurrent);
      rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent, iNew, 1);
      releasePageNotNull(pPg);
    }else{
      rc = allocateBtreePage(pBt, &pFree, &iNew, iFirst-1, BTALLOC_LE);
      assert( rc!=SQLITE_OK || iNew<iFirst );
      releasePage(pFree);
      if( rc==SQLITE_OK ){
        MemPage *pPg = 0;

        btreeGetPage(pBt, iPg, &pPg, 0);
        rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent,iNew,1);
        releasePage(pPg);
      }
    }
  }
  return rc;







<


>







3900
3901
3902
3903
3904
3905
3906

3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
      iNew = ++(*pnCurrent);
      if( iNew==PENDING_BYTE_PAGE(pBt) ) iNew = ++(*pnCurrent);
      rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent, iNew, 1);
      releasePageNotNull(pPg);
    }else{
      rc = allocateBtreePage(pBt, &pFree, &iNew, iFirst-1, BTALLOC_LE);
      assert( rc!=SQLITE_OK || iNew<iFirst );

      if( rc==SQLITE_OK ){
        MemPage *pPg = 0;
        releasePage(pFree);
        btreeGetPage(pBt, iPg, &pPg, 0);
        rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent,iNew,1);
        releasePage(pPg);
      }
    }
  }
  return rc;
Added test/concfault.test.












































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 2015 Aug 25
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains fault injection tests designed to test the concurrent
# transactions feature.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix concfault

# This test will not work with an in-memory journal, as the database will
# become corrupt if an error is injected into a transaction after it starts
# writing data out to the db file.
ifcapable !concurrent {
  finish_test
  return
}

do_test 1-pre1 {
  execsql {
    PRAGMA journal_mode = wal;
    CREATE TABLE t1(a PRIMARY KEY, b);
    INSERT INTO t1 VALUES(randomblob(1000), randomblob(100));
    INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
    INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
    INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
    INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
    DELETE FROM t1 WHERE rowid%2;
  }
  faultsim_save_and_close
} {}

do_faultsim_test 1.1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { 
    BEGIN CONCURRENT;
      INSERT INTO t1 VALUES(randomblob(1000), randomblob(100));
    COMMIT;
  }
} -test {
  faultsim_test_result {0 {}} 
  catchsql { ROLLBACK }
  faultsim_integrity_check
}

do_faultsim_test 1.2 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { 
    BEGIN CONCURRENT;
      INSERT INTO t1 VALUES(randomblob(1000), randomblob(100));
    ROLLBACK;
  }
} -test {
  faultsim_test_result {0 {}} 
  catchsql { ROLLBACK }
  faultsim_integrity_check
}

do_faultsim_test 1.3 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { 
    BEGIN CONCURRENT;
      DELETE FROM t1;
    COMMIT;
  }
} -test {
  faultsim_test_result {0 {}} 
  catchsql { ROLLBACK }
  faultsim_integrity_check
}

finish_test

Changes to test/concurrent.test.
443
444
445
446
447
448
449

450
451
452
} {1 {cannot modify application_id within CONCURRENT transaction}}
do_execsql_test 3.5 {
  COMMIT;
  PRAGMA user_version;
  PRAGMA application_id;
  SELECT * FROM t1;
} {10 0 a b c d}


finish_test








>



443
444
445
446
447
448
449
450
451
452
453
} {1 {cannot modify application_id within CONCURRENT transaction}}
do_execsql_test 3.5 {
  COMMIT;
  PRAGMA user_version;
  PRAGMA application_id;
  SELECT * FROM t1;
} {10 0 a b c d}


finish_test