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

Thead-safe library initialization #37

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

Thead-safe library initialization #37

wants to merge 5 commits into from

Conversation

yugr
Copy link
Owner

@yugr yugr commented Jan 18, 2025

@Artem-B you once worked on adding multi-threading support to Implib.so. Perhaps you could review this Pthread-based implementation? In particular I'm not sure I test this enough.

@yugr yugr self-assigned this Jan 18, 2025
@codecov-commenter
Copy link

codecov-commenter commented Jan 18, 2025

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.57%. Comparing base (c6ec69e) to head (d4b6bf5).

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #37      +/-   ##
==========================================
+ Coverage   88.49%   88.57%   +0.08%     
==========================================
  Files           1        1              
  Lines         391      394       +3     
==========================================
+ Hits          346      349       +3     
  Misses         45       45              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@Artem-B Artem-B left a comment

Choose a reason for hiding this comment

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

It's not clear, what exactly is intended to be protected by the mutex.

The patch appears to serialize the load_library call, the code seems to leave the door open for data races between calls modifying the data used by load_library(). E.g
nothing stops user from calling *_tramp_reset while load_library in another thread has already set lib_handle, but didn't set do_dlclose yet. It will reset lib_handle to NULL,
and we'll end up with the library never dlclosed.

I don't think we care much about making locking particularly fine-grained, so I would consider locking all API calls and guarantee thread safety for both code execution and the internal implib state.

As for the testing, thread sanitizer does a very good job catching threading issues, but it relies on comprehensive enough set of tests. I do not have much experience in creating such tests. That's part of the reason I'd rather rely on everything touching shared state being under lock so we have less risk of encountering the race conditions we didn't think of.

One useful way to think whether the code is thread safe is "if I stop this thread here, can I break things from other threads?". implib's call is small enough to make it feasible to do that as a thought experiment.

@yugr yugr changed the title Thead-safe initialization Thead-safe library initialization Jan 18, 2025
@yugr
Copy link
Owner Author

yugr commented Jan 18, 2025

The patch appears to serialize the load_library call, the code seems to leave the door open for data races between calls modifying the data used by load_library(). E.g nothing stops user from calling *_tramp_reset while load_library in another thread has already set lib_handle, but didn't set do_dlclose yet. It will reset lib_handle to NULL, and we'll end up with the library never dlclosed.

Right. This PR just touches the library initialization, not Implib's APIs which remain thread-unsafe as you noticed. I will support them in separate PR as they are less critical for the users (most don't even use them).

As for the testing, thread sanitizer does a very good job catching threading issues, but it relies on comprehensive enough set of tests. I do not have much experience in creating such tests. That's part of the reason I'd rather rely on everything touching shared state being under lock so we have less risk of encountering the race conditions we didn't think of.

Right, the added test already runs under Tsan (I even had to get rid double-checked locking because of this).

One useful way to think whether the code is thread safe is "if I stop this thread here, can I break things from other threads?". implib's call is small enough to make it feasible to do that as a thought experiment.

+1

Copy link
Contributor

@Artem-B Artem-B left a comment

Choose a reason for hiding this comment

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

LGTM for the stated goal of serializing library loading only.

}

for (int i = 0; i < N; ++i) {
if (0 != pthread_create(&tids[i], 0, run, &args[i]))
Copy link
Contributor

Choose a reason for hiding this comment

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

The run is very short-lived. It's possible for the launched thread to run and finish before the main thread manages to launch the next one.

A more robust way to ensure a race would be to make all threads block on something locked by the main thread, and then unlock all of them at once. E.g use pthread_barrier_wait in run to wait until the last thread has been launched.

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

Successfully merging this pull request may close these issues.

3 participants