Package: xapian-core / 1.4.3-2+deb9u3

fix-glass-cursor-bug.patch Patch series | download
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
Description: Fix glass bug with WritableDatabase cursors
 A long-lived cursor on a table in a WritableDatabase could get into
 an invalid state, which typically resulted in a DatabaseCorruptError
 being thrown with the message:
 .
 Db block overwritten - are there multiple writers?
 .
 But in fact the on-disk database is not corrupted - it's just that
 the cursor in memory has got into an inconsistent state.  It looks
 like we'll always detect the inconsistency before it can cause on-disk
 corruption but it's hard to be complete certain.
 .  
 The bug is in code to rebuild the cursor when the underlying table
 changes in ways which require that.  That's a fairly rare occurrence
 (with my C++ reproducer it happens 99 times out of 5000 commits).
 .   
 In chert the equivalent code just marks the cursor's blocks as not yet
 read, but in glass cursor blocks are reference counted and shared so we
 can't simply do that as it could affect other cursors sharing the same
 blocks.
 .   
 So instead the glass code was leaving them with the contents they
 previously had, except for copying the current root block from the
 table's "built-in cursor".  After the rebuild we seek the cursor to the
 same key it was on before, and that mostly works because we follow down
 each level in the Btree from the new root, except it can happen that the
 old cursor contained a block number which has since been released and
 reallocated, and in that case the block doesn't get reread and we try to
 use its old contents, which violates the rule that a parent can't be
 younger than its child and causes the exception.
 . 
 This commit fixes this by simply resetting the rebuilt cursor to match
 the current "built-in cursor" at all levels (not just the root), which
 is cheap because of the reference counting.
 .
 Reported with a reproducer by Sylvain Taverne.  Confirmed by David
 Bremner as fixing a problem in notmuch without a reduced reproducer.
Author: Olly Betts <olly@survex.com>
Bug-Debian: https://bugs.debian.org/906007
Origin: upstream
Forwarded: https://git.xapian.org/?p=xapian;a=commitdiff;h=70266397a517e213977f49c5b7c2c91389c88879
Last-Update: 2018-08-13

--- a/backends/glass/glass_cursor.cc
+++ b/backends/glass/glass_cursor.cc
@@ -73,6 +73,9 @@ GlassCursor::rebuild()
 {
     int new_level = B->level;
     if (new_level <= level) {
+	for (int j = 0; j < new_level; ++j) {
+	    C[j].clone(B->C[j]);
+	}
 	for (int j = new_level; j <= level; ++j) {
 	    C[j].destroy();
 	}
@@ -81,6 +84,7 @@ GlassCursor::rebuild()
 	C = new Cursor[new_level + 1];
 	for (int i = 0; i < level; ++i) {
 	    C[i].swap(old_C[i]);
+	    C[i].clone(B->C[i]);
 	}
 	delete [] old_C;
 	for (int j = level; j < new_level; ++j) {