https://bugs.openldap.org/show_bug.cgi?id=9983

          Issue ID: 9983
           Summary: operation_unlink files the operation before it is
                    fully unlinked
           Product: OpenLDAP
           Version: 2.5.13
          Hardware: All
                OS: All
            Status: UNCONFIRMED
          Keywords: needs_review
          Severity: normal
          Priority: ---
         Component: lloadd
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

In epoch based memory management, objects should only be submitted for
reclaiming when no actors can reach them unless they've done that before the
submission happened.

This is broken in operation_unlink():
It calls try_release_ref() at the beginning where the operation is added to the
to-reclaim list, only then it proceeds to unlink it from other objects.

The following sequence is then possible:
- current_epoch == 1 (no threads are alive in epoch == 0)
- in thread 1 (epoch = 1), try_release_ref() marks the object to be reclaimed
in current_epoch
- thread 2 activates and current_epoch is incremented (current_epoch == 2)
- thread 2 handles an Unbind for the operation's client and reaches
client_reset() (epoch == 2)
- thread 2 (client_reset) snapshots and clears client->c_ops (among other
things, c->c_ops links to our object)
- thread 1 finishes operation_unlink, deactivates and there are no more threads
in epoch == 1
- thread 3 activates and current_epoch is incremented (current_epoch == 3),
there are objects in epoch == 1, namely the object above which is now destroyed
(freed)
- thread 2 wakes up again and tries to call operation_abandon on the above
object, this accesses memory freed

epoch_append (and try_release_ref) should only be called when unlinking has
finished. I'm testing a patch right now.

-- 
You are receiving this mail because:
You are on the CC list for the issue.

Reply via email to