Session lock record with PHP 7.0.9 #269

Open
CassianoCarraro opened this Issue Aug 2, 2016 · 12 comments

Projects

None yet

9 participants

@CassianoCarraro

I'm using a Memcached session handler normally in PHP 5.6. But with PHP 7 session don't retrieved properly and the follow warning message was triggered in PHP error log: PHP Warning: session_start(): Unable to clear session lock record.

Any suggestion?

@datasage
datasage commented Aug 2, 2016

Session settings have changed quite a bit for php 7 version of the extension, you will probably need to tweak your settings a bit to get it to behave as it did in PHP 5.6

@sodabrew
Contributor
sodabrew commented Aug 3, 2016

Please state the version of php-memcached that you are using (or the git revision if you're building from source).

@CassianoCarraro

I tried to use repository and build php7 source branch, but in both case i have the same problem. The versions is as follows:

From repository
Memcached version: 3.0.0-dev
libmemcached version: 1.0.16

From php7 branch:
Memcached version: 3.0.0b1
libmemcached version: 1.0.18

@beniamin
beniamin commented Aug 18, 2016 edited

I had same problem and I resolved the issue by disabling session.lazy_write in php.ini

@arisro
Contributor
arisro commented Aug 22, 2016

Hey guys,

You can set memcached.sess_lock_expire to your max_execution_time value to avoid that bug from #266. This way the extension won't fall back to the max_execution_time value - which it reads incorrectly.

@CassianoCarraro

I disabled session.lazy_write and set memcached.sess_lock_expire according my max_execution_time, but the problem persists. I found that this problem occurs when many requests is sent in a short time to session_start() with a same session id. This can be simulated with a code that call session_start() and then add a sleep executing this script many times will throw this error. I think that have a problem to unlock session or another configuration is causing the problem.

@arisro
Contributor
arisro commented Aug 24, 2016 edited

@CassianoCarraro

In the case you describe, the error is normal.
Example:
0. See this: https://bugs.php.net/bug.php?id=72345. The maximum execution time is not affected by system calls, stream operations etc. So the time you wait for session_start() doesn't add to the execution time.

  1. You have max_execution_time = memcached.sess_lock_expire = 30s
  2. You fire a request that keeps the session locked 3s let's say. If you fire 11 requests, they are serialized by the session lock. Your requests will go through 1 by 1.
  3. The first request goes in immediately and locks the session for 3s. The seconds request waits 3s then he locks it for another 3s. The third request will wait in total 6s, then lock for 3s, and so on.
  4. The 11th request has to wait 30s. Since session_start() doesn't add to the exection time, you won't get a max execution time error. You will get instead a warning, because of the session locking timeouts (which you can control with memcached.sess_lock_retries, memcached.sess_lock_wait_min/max).
    Once this timeout happens, your request will go through and be executed - ignoring the lock so to say.

So this is another problem, and is not actually an issue cause by this extension. The issue #266 consists in the session lock being permanently set (with 0 TTL) so you reach the timeout limit on any request - and the lock is not removed even after the timeout, when the request is processed.

@beniamin

My problem is with parallel requests. If I have an ajax request running and I send another request, both requests are stopped and receive 500 with error from first post.
I tried to set max_execution_time = memcached.sess_lock_expire, but didn't solve my problem.
Only disabling session.lazy_write solved my problem.

@idmssvep

I have the same issue, i run a lot of paralell requests and i have repeating "Unable to clear session lock record" fatals. I disabled lazy write and tried following memcached config:

memcached.sess_lock_expire 7200
memcached.sess_lock_max_wait not set
memcached.sess_lock_retries 5
memcached.sess_lock_wait not set
memcached.sess_lock_wait_max 120000
memcached.sess_lock_wait_min 0
memcached.sess_locking 1

with:
Version 3.0.0-dev
libmemcached version 1.0.16

With older versions on php 5.4 base i have absolutely no issues. It gives me a feeling that on PHP7 they are processed much faster and due to this fact create more blocking requests. One question: Is this issue fixed to PHP 7.0.9, so a up or downgrade could help?

@arielkung

Confirming here in php 7.0.12 if you set a fixed value for memcached.sess_lock_expire the issue goes away.
Message "PHP Warning: session_start(): Unable to clear session lock record." will appear anyway if your session is locked more than the time you set of course.

@bzabos
bzabos commented Jan 7, 2017

Please read up on how these values are consumed: https://github.com/php-memcached-dev/php-memcached/blob/master/memcached.ini

Increasing sess_lock_wait_max is only increasing the maximum seconds to which php will perform its exponential back off routine for retries. Increasing this value does nothing when sess_lock_wait_min is left untouched. If we want php to continue retrying at an acceptable interval, I don't believe these are the keys we should be adjusting. Lowering sess_lock_expire is just highjacking the session from other, long running, requests — is that the desired behaviour? Disabling lazy_write also seems like a bad idea.

Can anyone see why the solution wouldn't be to simply increase sess_lock_retries to a number that would result in an acceptable wait time for your specific scenario?

Eg. Where default sess_lock_wait_min=1000 and default sess_lock_wait_max=2000 and increased sess_lock_retries=10, our retry wait will accumulate as 1s+2s+2s+... Ns, giving us a total wait of 19 seconds of waiting and retrying for session lock to be released by other requests; logically, it makes sense to formulate rough equality with your max_execution_time.

@woolardfa

For our Moodle site, we use memcached for PHP sessions. Because of the way Moodle uses the session handler in its AJAX calls (several issued before main page request finishes) we often get blocked session_start() calls. See this bug and this bug for details.

To get the new version to behave like the old one, we set the lock_wait_min and _max to the same reduced value of 150. This makes the spin lock retry 150 msec, as was the default in 2.2.x. Moodle config default is to wait a max of 120 secs to attain a session lock, so we set the retry count to 800 (120 / .15).

One or two seconds seems to be much to long to wait between attempts; much better to make several frequent attempts waiting (sleeping) only 150 msec at a time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment