-
Notifications
You must be signed in to change notification settings - Fork 501
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
Ability to terminate thread-pool upon shutdown #903
base: main
Are you sure you want to change the base?
Conversation
rayon-core/src/thread_pool/mod.rs
Outdated
/// Terminates the threads, renders the threadpool unusable. | ||
/// This is useful for testing (miri) if the thread-pool is static. | ||
/// It should be used upon shutdown only | ||
pub fn terminate(&mut self) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a &mut ThreadPool
is available, couldn't it just be mem::replace
d with a newly built thread pool, dropping the old one and thereby terminating its threads without creating this sharp edge in the API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to terminate https://github.com/pola-rs/polars/blob/master/polars/polars-core/src/lib.rs#L44-L53 this thread-pool when the test is complete. Using the POOL static
seems to be a good practice, I wouldn't want to change that.
Context: pola-rs/polars#1927
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The static will only ever give you access to a shared reference &ThreadPool
(POOL
will implement Deref<Target=ThreadPool>
, not DerefMut<Target=ThreadPool>
), so it seems like you will not be able to call the above method in the first place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From reading the above context, if you really need to terminate that thread pool, you probably need to put it behind a RwLock
or something similar inside the lazy_static
so that you can get access to an exclusive reference &mut ThreadPool
in which case you can just mem::replace
it with a newly created one. (This would also imply that your tests need to take that lock to install any jobs within that thread pool.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamreichold thanks, you are right. Fortunately I can remove mut
and just use &self
. Does it look better now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I've compiled the changed rayon&polars and the test using miri succeeds (by adding POOL.terminate();
at the end of the test)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it technically works, this would need to be unsafe
AFAIU, e.g. look at line 277 in the diff: Not being able to terminate the registry while the thread pool is still in use appears to be a safety invariant that could be broken by calling terminate
and then trying to use the thread pool again.
Hence, I would suggest not adding this API (neither unsound as-is nor unsafe
) and rely on putting the thread pool within an RwLock
for the tests (where the additional cost of taking the lock is probably bearable). But this is just my drive-by-code-reviewer opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where the additional cost of taking the lock is probably bearable
I see now that you want to terminate in the tests, but POOL
itself is used in production code where the RwLock
option is not feasible. This would imply having this as an unsafe
method.
But then again, if you can use unsafe
and you can ensure that your borrow is unique, you could probably accomplish the same using an UnsafeCell
and mem::replace
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once again, you are right about the unsafe
required and it's good to have it there (since it supposed to be run in tests in teardown only, not in prod code, so one should read the docs again). I've added the keyword.
The other option you've mentioned: I'm not a seasoned Rust developer, so I'd ask @ritchie46 or @jorgecarleitao what do they think about that.
Thanks a lot, I've already learned a lot today.
While `.terminate()` will leave the thread-pool in corrupt state, it helps debugging and testing.
I was wrong, somehow I missed that it still doesn't work:
I've checked that in the ThreadInfo it's all |
While
.terminate()
will leave the thread-pool in corrupt state, it helps debugging and testing.