mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 07:17:55 +03:00
Fix stack overflow when destroying long Journal
Summary: While destroying JournalDelta entries, unzip the chain as we go and destroy each entry one by one. This prevents the stack from overflowing on long JournalDelta chains and should fix some flaky tests. Reviewed By: wez Differential Revision: D9355365 fbshipit-source-id: 31af124d318ca5d7a84314b707e1b3c71b2ccaa9
This commit is contained in:
parent
8b4841ef82
commit
e6ab9d58a2
@ -50,6 +50,17 @@ JournalDelta::JournalDelta(
|
||||
: changedFilesInOverlay{{oldName.copy(), PathChangeInfo{true, false}},
|
||||
{newName.copy(), PathChangeInfo{true, true}}} {}
|
||||
|
||||
JournalDelta::~JournalDelta() {
|
||||
// O(1) stack space destruction of the delta chain.
|
||||
JournalDeltaPtr p{std::move(previous)};
|
||||
while (p && p.unique()) {
|
||||
// We know we have the only reference to p, so cast away constness because
|
||||
// we need to unset p->previous.
|
||||
JournalDelta* q = const_cast<JournalDelta*>(p.get());
|
||||
p = std::move(q->previous);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<JournalDelta> JournalDelta::merge(
|
||||
SequenceNumber limitSequence,
|
||||
bool pruneAfterLimit) const {
|
||||
|
@ -72,6 +72,8 @@ class JournalDelta {
|
||||
*/
|
||||
JournalDelta(RelativePathPiece oldName, RelativePathPiece newName, Replaced);
|
||||
|
||||
~JournalDelta();
|
||||
|
||||
/** the prior delta and its chain */
|
||||
JournalDeltaPtr previous;
|
||||
/** The current sequence range.
|
||||
|
@ -155,3 +155,19 @@ TEST(Journal, mergeRemoveCreateUpdate) {
|
||||
true,
|
||||
merged->changedFilesInOverlay[RelativePath{"test.txt"}].existedAfter);
|
||||
}
|
||||
|
||||
TEST(Journal, destruction_does_not_overflow_stack_on_long_chain) {
|
||||
Journal journal;
|
||||
size_t N =
|
||||
#ifdef NDEBUG
|
||||
200000 // Passes in under 200ms.
|
||||
#else
|
||||
40000 // Passes in under 400ms.
|
||||
#endif
|
||||
;
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
auto delta = std::make_unique<JournalDelta>(
|
||||
"foo/bar"_relpath, JournalDelta::CHANGED);
|
||||
journal.addDelta(std::move(delta));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user