Skip to content

[Lock] Scoped Lock #22115

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

Closed
wants to merge 1 commit into from
Closed

[Lock] Scoped Lock #22115

wants to merge 1 commit into from

Conversation

fbourigault
Copy link
Contributor

@fbourigault fbourigault commented Mar 22, 2017

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets N/A
License MIT
Doc PR soon

This add to the just-born Lock component a scoped lock.

A scoped lock is a lock which will get automatically released when destructed.

Usage

class MyService
{
    private $lockFactory;

    public function __construct(LockFactoryInterface $lockFactory)
    {
        $this->lockFactory = $lockFactory;
    }

    public function run()
    {
        $lock = $this->lockFactory->createScopedLock(__METHOD__);
        $lock->acquire();

       // some locked job

        if (/* early return test*/) {
            return; //the lock will be released when leaving the function scope.
        }
        
        try {
             //some other locked job
        } catch (\Exception $e) {
             //no need to release the lock. it will be automatically released when leaving the function scope.
        }
        
    } //lock is automatically released here
}

@fabpot
Copy link
Member

fabpot commented Mar 22, 2017

ping @jderusse

@fbourigault
Copy link
Contributor Author

Do we include the documentation in the main component PR, or I create a new one based on the first one?

@fbourigault
Copy link
Contributor Author

Tests are failing for php 7.1 with lowest dependencies. It does not looks related to my PR https://travis-ci.org/symfony/symfony/jobs/214019847#L3293-L3323.

@jderusse
Copy link
Member

Trying the solve test failure in #22119

@jderusse
Copy link
Member

LGTM.
This is a clever idea, and would simplify several use case of this component.

@robfrawley
Copy link
Contributor

robfrawley commented Mar 23, 2017

While I generally think this is a great feature, there are some caveats to relying on the destructor for releasing locks where the Lock Component's destructor will not be called, causing the lock to persist, specifically:

  • If throw is called in another destructor
  • If exit is called in another destructor
  • If exit is called from a shutdown function registered via register_shutdown_function (depending on PHP version, it seems)
  • If there is a fatal error

The lock will persist in all the above, and possibly other, cases. We should be clear about these caveats in the documentation for this PR, IMHO.

@jderusse
Copy link
Member

Stores are made to avoid to keep a lock for ever (segfault and brutal interrupt are handled) thank to the TTL mechanism (but it's not perfect)

But you're right. We can add to the list:

  • if the variable is copied (stored in a kind of cache or whatever)
  • after a circular reference assignment of the lock variable, we don't know when the GC will call the destructor

@fbourigault
Copy link
Contributor Author

@robfrawley, all cases you listed are not specific to the scoped lock. So like @jderusse said, you can only rely on the lock timeout.

What about a warning in the scoped lock dock about the two points @jderusse listed?

Copy link
Contributor

@greg0ire greg0ire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice contribution!

*/
public function createScopedLock($resource, $ttl = 300.0)
{
$lock = $this->createLock($resource, $ttl);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughtless OTV, consider removing it.

* Create a scoped lock for the given resource.
*
* @param string $resource The resource to lock
* @param float $ttl maximum expected lock duration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what unit? Please document that.

namespace Symfony\Component\Lock;

/**
* ScopedLock encapsulate a LockInterface which is automatically released when destructed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"encapsulateS"

}

/**
* Automatically release the underlying lock when object is destructed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"when the object"

@fbourigault
Copy link
Contributor Author

Broken tests are addressed in #22122

@fbourigault
Copy link
Contributor Author

@greg0ire I addressed all changes you requested.
I also added parameters description for Lock.

Copy link
Contributor

@greg0ire greg0ire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

@robfrawley
Copy link
Contributor

@fbourigault I just think we should mention these caveats in the documentation PR, is all.

@nicolas-grekas
Copy link
Member

I'm 👎 here. This makes releasing totally implicit. That's a foot gun to me.

  • HHVM doesn't have the same destructing rules than PHP (they can even be not called)
  • when a custom error handler keeps the $context, the lock will not be released
  • same in the cases listed by @robfrawley (gc, stack traces, etc.)

Adding a decorator to provide an unreliable behavior looks like... unreliable, thus my stand.
If you want that, but in a predictable way, just wrap in a try+finally block.

@fabpot
Copy link
Member

fabpot commented Mar 23, 2017

Closing for the reasons explained by @nicolas-grekas

@fabpot fabpot closed this Mar 23, 2017
fabpot added a commit that referenced this pull request Oct 1, 2017
…jderusse)

This PR was squashed before being merged into the 3.4 branch (closes #22132).

Discussion
----------

[Lock] Automaticaly release lock when user forget it

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

The objective of this PR is to automatically release the Lock when the user forget to call the `release` method (like the `fclose` function does in, php core).
The implementation is comparable to #22115 but the purpose is not the same.

I create a new PR to not mix things.

Commits
-------

2eedc1f [Lock] Automaticaly release lock when user forget it
@fbourigault fbourigault deleted the scoped-lock branch September 17, 2018 22:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants