Skip to content

Commit f1d5e90

Browse files
committed
Fixes #3678
Refactor so that marks_with_checkpoints is just changed in one place, not arbitrarily access it. Ref counts had the same changes in a previous commit. Fixes a bug for loaded persistent checkpoints where the re-created checkpoints did not get their reference counting correct. This closes #3678
1 parent bc524da commit f1d5e90

File tree

3 files changed

+21
-15
lines changed

3 files changed

+21
-15
lines changed

src/GdbServer.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,6 +2250,10 @@ Checkpoint::Checkpoint(ReplayTimeline& timeline, TaskUid last_continue_tuid,
22502250
mark = timeline.add_explicit_checkpoint();
22512251
} else {
22522252
mark = timeline.mark();
2253+
const auto prior = timeline.find_closest_mark_with_clone(mark);
2254+
if(prior) {
2255+
prior->get_internal()->inc_refcount();
2256+
}
22532257
}
22542258
}
22552259

src/ReplayTimeline.cc

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ ReplayTimeline::Mark ReplayTimeline::mark() {
225225
ReplayTimeline::Mark ReplayTimeline::recreate_mark_from_data(const MarkData& mark_data, ReplaySession::shr_ptr session) {
226226
Mark result;
227227
auto m = make_shared<InternalMark>(this, mark_data, session);
228-
228+
m->inc_refcount();
229229
auto& mark_vector = marks[m->proto.key];
230230
mark_vector.push_back(m);
231231
result.ptr = mark_vector.back();
@@ -235,11 +235,7 @@ ReplayTimeline::Mark ReplayTimeline::recreate_mark_from_data(const MarkData& mar
235235
void ReplayTimeline::register_mark_as_checkpoint(Mark& m) {
236236
DEBUG_ASSERT(m.ptr && m.ptr->checkpoint && "Can't register mark as checkpoint if no checkpoint exists");
237237
auto key = m.ptr->proto.key;
238-
if (marks_with_checkpoints.find(key) == marks_with_checkpoints.end()) {
239-
marks_with_checkpoints[key] = 1;
240-
} else {
241-
marks_with_checkpoints[key]++;
242-
}
238+
increase_mark_with_checkpoints(key);
243239
m.ptr->inc_refcount();
244240
}
245241

@@ -313,6 +309,15 @@ ReplayTimeline::Mark ReplayTimeline::lazy_reverse_singlestep(const Mark& from,
313309
return Mark();
314310
}
315311

312+
void ReplayTimeline::increase_mark_with_checkpoints(
313+
const MarkKey& key) noexcept {
314+
if (marks_with_checkpoints.find(key) == marks_with_checkpoints.end()) {
315+
marks_with_checkpoints[key] = 1;
316+
} else {
317+
marks_with_checkpoints[key]++;
318+
}
319+
}
320+
316321
ReplayTimeline::Mark ReplayTimeline::add_explicit_checkpoint() {
317322
DEBUG_ASSERT(current->can_clone());
318323

@@ -321,11 +326,7 @@ ReplayTimeline::Mark ReplayTimeline::add_explicit_checkpoint() {
321326
unapply_breakpoints_and_watchpoints();
322327
m.ptr->checkpoint = current->clone();
323328
auto key = m.ptr->proto.key;
324-
if (marks_with_checkpoints.find(key) == marks_with_checkpoints.end()) {
325-
marks_with_checkpoints[key] = 1;
326-
} else {
327-
marks_with_checkpoints[key]++;
328-
}
329+
increase_mark_with_checkpoints(key);
329330
}
330331
m.ptr->inc_refcount();
331332
return m;
@@ -798,11 +799,9 @@ ReplayTimeline::Mark ReplayTimeline::recreate_marks_for_non_explicit(const Check
798799
// first add the mark with an actual clone, this is not a GDB checkpoint, but an RR checkpoint
799800
auto mark = recreate_mark_from_data(cp.clone_data, clone);
800801
reverse_exec_checkpoints[mark] = estimate_progress_of(*clone);
801-
mark.get_internal()->inc_refcount();
802802
register_mark_as_checkpoint(mark);
803803
// then add the mark with no clone, the one that will be visible to GDB, i.e. non explicit checkpoint
804804
Mark result = recreate_mark_from_data(*cp.non_explicit_mark_data, nullptr);
805-
// auto internal = make_shared<InternalMark>(this, *cp.non_explicit_data, nullptr);
806805
return result;
807806
}
808807

@@ -1736,8 +1735,8 @@ std::shared_ptr<ReplayTimeline::Mark> ReplayTimeline::find_closest_mark_with_clo
17361735
for(auto it = std::rbegin(marks_found->second); it != std::rend(marks_found->second); it++) {
17371736
DEBUG_ASSERT(it->get() != nullptr);
17381737
if((*it)->checkpoint) {
1739-
std::shared_ptr<Mark> result = std::make_shared<Mark>();
1740-
result->ptr = *it;
1738+
auto result = std::make_shared<Mark>();
1739+
result->ptr = *(it);
17411740
return result;
17421741
}
17431742
}

src/ReplayTimeline.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ class ReplayTimeline {
147147
*/
148148
void remove_explicit_checkpoint(const Mark& mark);
149149

150+
/** Find mark that has `key` and increase the checkpoint count for that mark. */
151+
void increase_mark_with_checkpoints(const MarkKey& key) noexcept;
152+
150153
/**
151154
* Return true if we're currently at the given mark.
152155
*/

0 commit comments

Comments
 (0)