Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cats: add missing database locks #1787

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

sebsura
Copy link
Contributor

@sebsura sebsura commented Apr 18, 2024

Thank you for contributing to the Bareos Project!

By default, bareos db connections get shared by multiple jobs/threads. It is of utmost importance to ensure that those shared connections only get written to/read from if the calling thread has acquired the lock.

This PR by no means ensures that this is done correctly everywhere, but the start of an ongoing process to weed out every race condition in the database code.

This PR adds some missing locks as well as assertions that locks were taken correctly at the relevant places.
Additionally it renames bac_cursor_ to bar_cursor_.

Please check

  • Short description and the purpose of this PR is present above this paragraph
  • Your name is present in the AUTHORS file (optional)

If you have any questions or problems, please give a comment in the PR.

Helpful documentation and best practices

Checklist for the reviewer of the PR (will be processed by the Bareos team)

Make sure you check/merge the PR using devtools/pr-tool to have some simple automated checks run and a proper changelog record added.

General
  • Is the PR title usable as CHANGELOG entry?
  • Purpose of the PR is understood
  • Commit descriptions are understandable and well formatted
  • Required backport PRs have been created
Source code quality
  • Source code changes are understandable
  • Variable and function names are meaningful
  • Code comments are correct (logically and spelling)
  • Required documentation changes are present and part of the PR
Tests
  • Decision taken that a test is required (if not, then remove this paragraph)
  • The choice of the type of test (unit test or systemtest) is reasonable
  • Testname matches exactly what is being tested
  • On a fail, output of the test leads quickly to the origin of the fault

@sebsura sebsura marked this pull request as draft April 18, 2024 13:28
@sebsura sebsura self-assigned this Apr 29, 2024
This function is not safe to use if you dont actually own the lock,
but misuse should hopefully lead to a crash anyways.
@sebsura sebsura force-pushed the dev/ssura/master/fix-database-locking branch from aabaf91 to c83d9a4 Compare April 29, 2024 06:21
@sebsura sebsura marked this pull request as ready for review April 29, 2024 06:21
This is not checked in case of private connections since they are not
shared automatically.  It probably makes sense to also check them
since they might get shared by accident (e.g. setting a pointer in jcr
and then another thread accessing that jcr).
@sebsura sebsura force-pushed the dev/ssura/master/fix-database-locking branch from c83d9a4 to f438920 Compare April 29, 2024 12:50
@arogge arogge self-requested a review May 14, 2024 09:43
Copy link
Member

@arogge arogge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not happy with the amount of calls to AssertOwnership(), especially as it looks pretty expensive. However, I don't have a great idea how to improve it right now.
I'll see if I can come up with an idea over the weekend...

@@ -828,6 +844,7 @@ void BareosDbPostgresql::SqlUpdateField(int i)

SQL_FIELD* BareosDbPostgresql::SqlFetchField(void)
{
AssertOwnership();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have any idea how this will influence runtime?
SqlFetchField() is called a lot in pretty tight loops.
Its happy-path boils down to:

  1. integer comparison
  2. nullptr check
  3. boolean check
  4. add two pointers (for array access)
  5. integer increment

Calling AssertOwnership() while assuming we're on Linux, it is completly inlined, on the happy path, and having is_private_ == false:

  1. boolean check
  2. pointer dereference
  3. integer equality comparison
  4. integer comparison
  5. library call to pthread_self() (cannot be inlined)
  6. long integer equality comparison (always inlined from pthread_equal())

I don't say this will be a performance issue. But it definitely looks like could be. Especially with the redundant check in SqlUpdateField() above we would call AssertOwnership() twice for each field.

@@ -800,6 +815,7 @@ uint64_t BareosDbPostgresql::SqlInsertAutokeyRecord(const char* query,

void BareosDbPostgresql::SqlUpdateField(int i)
{
AssertOwnership();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SqlUpdateField() is only called by SqlFetchField(), so this check is redundant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants