Skip to content

Replication: enable() clears "disabled" after starting the session, where disable() sets it before stopping one #924

Description

@vharseko

LDAPReplicationDomain.disable() sets disabled = true before disableService(), so a replay thread reads the flag of a domain which is going away before its session is stopped. enable() does not mirror it: it calls enableService() and clears disabled two statements later.

// disable()
disabled = true;
disableService();
...
// enable()
enableService();
sessionGeneration++;

disabled = false;

enableService() ends with startListenService(), so the listener can take a delivery, list it and hand it to a replay thread while disabled is still true. That thread reads the guard at the top of the replay loop, gives up on the change - and abandonReplay() returns without asking for it again, because a domain which is going away owns its session. The change stays listed, uncommitted and owned by nobody, so this domain's ServerState is held back until something else restarts the session.

The window is two statements wide and nothing in the protocol can be made to land inside it, so this is an invariant to hold rather than a bug to reproduce. Clearing the flag before enableService() closes it, and putting it back if enableService() throws keeps the other half: a domain whose session could not be started owns it the way a disabled one does.

Worth doing with the session generation of #922 rather than alone: a replay thread which survived disable() reads that flag too, and neither order of these two statements is right for it (#908).

Found while reviewing #892.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions