-
-
Notifications
You must be signed in to change notification settings - Fork 341
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
Problems with trio.Lock()
across multiple tasks
#3035
Comments
I'm not sure how I feel about adding a keyword argument to
I think that this could error when you run
|
Let's set lock = trio.Lock()
async with trio.open_nursery() as nursery:
nursery.start_soon(lock.acquire)
nursery.start_soon(lock.acquire) IMO instead of hanging forever, we should raise |
I agree; |
I think so long as we get a |
Erroring on lock = trio.Lock()
async with trio.open_nursery() as nursery:
nursery.start_soon(lock.acquire)
await lock.acquire() Is easy & straightforward, adding a check in But the other cases are definitely more complicated, since the other task(s) might start waiting before the task owner exits. I think the way to go is to
I don't think this requires a big performance hit, but we'd likely need to add some overhead whenever acquiring/releasing a lock, which perhaps partially could be traded off with more logic in |
I think better than a parent nursery check is just checking if the task is running. But yeah I'm not sure how to handle the other cases. Should there be a way to "poison" a parking lot? |
Another way of implementing it (inspired by @mikenerone) is having an |
Here's my latest idea: we can have a global dictionary of task -> a list (not a set because need to allow multiple of the same element) of parking lots, w/ an interface like Then lock uses that to have its parking lot broken if the task gets killed without releasing the lock. We can document this for use for anything that expects a task to release something but didn't. |
The lock initiates it? Trying to flesh this out:
|
Yeah, if I understand what you're asking.
We don't have to expose
The error should probably contain a reference to the task that caused things to break. Maybe a subclass of |
How to handle future improvements when we can have multiple guest runs able to run at once? |
The |
why is it necessary to allow multiple of the same element? It's not required for lock, so I'm guessing you're thinking of some external scenario? Opened #3081 with an initial implementation. It needs some polish but the overall approach looks solid |
Yeah I was thinking of a semaphore (cause it's still bad form to forget to release) and reentering within the same task. |
This made me look more into the other sync primitives, and |
We can probably let this issue stay locked and if somebody requests |
Some time ago - never mind how long precisely - having a little coordination between tasks and nothing particular to interest me in semaphores, I saw our
RuntimeError("can't release a Lock you don't own")
.I approve pretty strongly of keeping things local by default; it prevents all sorts of bugs and
trio.Semaphore
is right there if you need something without this limitation. But two further observations prompted this issue:trio.Semaphore()
is considerably more powerful and flexible in general. By the principle of least power, it might be nice to havetrio.Lock(*, allow_outside_release: bool = False)
or something along those lines.The text was updated successfully, but these errors were encountered: