-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
lru.LRU is not thread-safe; session cache maintenance (web3._utils.request) can crash the interpreter #1847
Comments
Should fix the segfaults we saw in gevent due to the non-thread safe use of LRU cache in web3.py request's session cache. As very well explained here by @jamadden: rotki#2132 (comment) This can all be reverted once ethereum/web3.py#1847 is fixed in web3.py side.
Wow, thanks for the report @jamadden! Will put this near the top of our todo list. |
The issue occurred in our setup (> 8 threads, various endpoints) quite stably. Synchronizing the cache access indeed solved the problem. |
@kclowes no, it seems #2407 is not a PR. from typing import Callable
import threading
import web3._utils.request
lock = threading.Lock()
def locked(fn: Callable) -> Callable:
def inner(*args, **kwargs):
with lock:
return fn(*args, **kwargs)
return inner
web3._utils.request.cache_session = locked(web3._utils.request.cache_session)
web3._utils.request._get_session = locked(web3._utils.request._get_session) |
Oops, I meant #2409. I think that's about equivalent to what you have. Thanks for the example! |
Resolved in #2409 for web3.py |
Hey @fselmo sorry for the ping but has this been backported to v5? And if yet in which release? |
Hey @LefterisJP, this was added to edit: Just released in web3.py v5.31.2 |
Thank you so much @fselmo. That was a really fast response and action. Appreciate it! |
The awesome guys at web3.py included the fix for ethereum/web3.py#1847 in that release
The awesome guys at web3.py included the fix for ethereum/web3.py#1847 in that release
What was wrong?
In #876, code was added to close sessions as they are evicted from the session cache. But in the presence of multiple threads this can lead to interpreter crashes, because
lru.LRU
is not thread safe. If, while running the callback function a thread switch happens, and that other thread also attempts to add a new session or otherwise manipulate the session cache, the interpreter can crash. (When we re-enter thelru.LRU
object, the internal state of the object is inconsistent while the callback is running. Because the callback is arbitrary Python code, it can easily drop the GIL.)This was originally reported in rotki/rotki#2132. There, they're using greenlets, but its easy to demonstrate the crash also using threads (a sample script is in that issue).
How can it be fixed?
Adding a lock around uses of
_session_cache
ought to fix the problem.The text was updated successfully, but these errors were encountered: