Skip to content

Changing a session table that has gone back to the pool, or belongs to another owner, is only logged and goes through #1736

Description

@AlexKirkouski

Description

Session tables are handed out from a pool and go back to it when the code that took one is done with it. Working with a table after that — or with one that belongs to somebody else — is checked, but the check only writes a line into the assert log and the statement runs anyway.

What runs is silent damage. A change of a table that is already free fills it for whoever gets it next, so that code reads its own rows plus somebody else's. A change of another owner's live table corrupts data the other side is still using. In both cases nothing fails, nothing is retried, and the result surfaces later as wrong data with no connection to the place that caused it.

The same holds for reading a table whose owner is gone: the query returns rows that may already belong to a new owner.

There is no way for an application to run into this by itself — a stale reference is kept inside the platform. But when it happens, the application is the one that gets the wrong numbers.

Reason

An error at the moment of the violation names the operation and the owner that broke the rule; the current log line is written long before anyone notices the data is wrong, and by then the table has usually been handed on again.

Two things have to be done in order, and the first is what makes this more than a two-line change:

  • the registry of issued tables can currently be read only under the lock that serializes issuing and returning ("все использования assertLock"). The check runs from places where that lock cannot be taken — a change made from an INTERNAL DB callback already holds the connection lock, and taking the table lock on top of it is exactly the order that deadlocks against a table being returned in parallel. So the registry has to become safe to read without that lock first;
  • only then can the check refuse the operation instead of logging it. The read check has to stay a log even then: a query legitimately joins tables of several owners, and it runs from a point where the connection lock is already held.

A setting should restore the previous behavior for an installation that hits this on an upgrade.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions