On Fri, Aug 8, 2014 at 11:35 AM, Neil D. Cerutti <ne...@norwich.edu> wrote:
> On 8/8/2014 12:16 PM, Chris Angelico wrote: > >> On Sat, Aug 9, 2014 at 2:05 AM, Neil D. Cerutti <ne...@norwich.edu> >> wrote: >> >>> Perhaps defer release, a la a common Go pattern: >>> >>> with contextlib.ExitStack() as stack: >>> acquired = lock.acquire(blocking=False) >>> if acquired: >>> stack.callback(lock.release) >>> do_stuff >>> >> >> There's a race condition in that - an unexpected exception could >> happen between those two. Are you able to set the callback to be a >> "release if acquired" atomic operation? >> > > Doesn't any natural looking use of blocking=False suffer from the same > race condition? What's the correct way to use it? > > Here's another attempt at context managing: > > @contextlib.contextmanager > def release_if_acquired(lock, blocking=True, timeout=-1): > acquired = lock.acquire(blocking, timeout) > if acquired: > yield acquired > lock.release() > else: > yield acquired > What I'd probably do is: @contextlib.contextmanager def release_if_acquired(lock, blocking=True, timeout=-1): acquired = lock.acquire(blocking, timeout) try: yield acquired finally: if acquired: lock.release() However, there is still the chance that a interrupt signal (ctrl+c) could prevent the lock from being released, but I think the only 100% solution would be to write the code in C where it cannot be interrupted within Python. The OS could still interrupt or kill the thread, but in that case, I don't think there is anything you can do... > with release_if_acquired(lock, blocking=False) as acquired: > if acquired: > > do_stuff > >
-- https://mail.python.org/mailman/listinfo/python-list