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

Possible data races on global mutable state in Base? #49778

Open
NHDaly opened this issue May 11, 2023 · 4 comments
Open

Possible data races on global mutable state in Base? #49778

NHDaly opened this issue May 11, 2023 · 4 comments
Labels
multithreading Base.Threads and related functionality

Comments

@NHDaly
Copy link
Member

NHDaly commented May 11, 2023

Following up from #49746 / #49774, I thought I'd try to spend a few minutes auditing all the other global mutable data structures we have in Base for thread safety. I didn't check every single one, but these are the ones that stood out to me as possibly racy and needing a lock.

There were others, but I believe they are only ever mutated during startup, when loading the sysimg, so I left them out.

Here's the list of questionable items - I would definitely appreciate a second opinion from other devs. Thanks!

Thanks!

CC: @kpamnany / @vchuravy / @timholy / @vtjnash as people to tag according to git blame

@NHDaly NHDaly added the multithreading Base.Threads and related functionality label May 11, 2023
@NHDaly
Copy link
Member Author

NHDaly commented May 11, 2023

(I used LookingGlass.jl to do this search, via):

julia> for n in LookingGlass.module_globals_names(Base, constness=:const, mutability=:mutable)
           println("const $n")
       end
const ACTIVE_PROJECT
const ARGS
const BUILD_TRIPLET
const COMPILETIME_PREFERENCES
const DATAROOTDIR
const DEFAULT_LOAD_PATH
const DEPOT_PATH
const DL_LOAD_PATH
const DOCDIR
const ENABLE_PRECOMPILE_WARNINGS
...

@vtjnash
Copy link
Member

vtjnash commented May 12, 2023

This is an awesome list! A couple you also missed from my list include:

Looks like most of those just need a simple lock associated with each.

The toplevel_load flag is conceptually flawed though, as is the new loading_extension global that is similar to it

julia/base/loading.jl

Lines 1618 to 1619 in 5039d8a

# require always works in Main scope and loads files from node 1
const toplevel_load = Ref(true)

There was a brief observation recently that those may be semi-equivalent to isempty(package_locks)
bf379e2#diff-ec80afe9f8ff182765c73ed3fc35a103b561f873a52b1dfe1ce135e4e5f9a2cfL1673

@NHDaly
Copy link
Member Author

NHDaly commented May 12, 2023

Excellent! Thanks for the details, and the confirmation. 👍

@NHDaly
Copy link
Member Author

NHDaly commented May 12, 2023

Looks like most of those just need a simple lock associated with each.

The toplevel_load flag is conceptually flawed though, as is the new loading_extension global that is similar to it

Yeah, cool. I would advocate for just slapping a lock around each of these as a first pass, and then coming back and fixing any other conceptual / correctness issues with the code in question in a later pass. I don't want us to be hunting down memory corruptions in production again like this again if we can avoid it.

As observed in #49774, these are obviously quite problematic. The failures can be severe, inexplicable, and just infrequent enough to make them difficult to track down.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
multithreading Base.Threads and related functionality
Projects
None yet
Development

No branches or pull requests

2 participants