Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does PHP occasionally hang on session_start()

NB This is not a dupe of PHP session_start() causing HTTP requests to hang (and other similarly named questions on SO), as my hang is occasional, not permanent.

Using Ubuntu 12.04, Magento, PHP-FPM (5.4) and default PHP session handler (with files on ext4).

Incidentally (once per month) all PHP processes hang on session_start() (according to fpm-slow.log):

[24-Sep-2014 11:03:04]  [pool www] pid 24259
script_filename = /data/web/public/index.php
[0x00007f00b4ec6480] session_start() /data/web/public/includes/src/__default.php:7687
[0x00007f00b4ec6130] start() /data/web/public/includes/src/__default.php:7730
[0x00007f00b4ec5fb8] init() /data/web/public/includes/src/__default.php:8086
[0x00007f00b4ec5e30] init() /data/web/public/includes/src/__default.php:33902
[0x00007f00b4ec5bd0] __construct() /data/web/public/includes/src/__default.php:23841
[0x00007f00b4ec5ae8] getModelInstance() /data/web/public/app/Mage.php:463
[0x00007f00b4ec59c8] getModel() /data/web/public/app/Mage.php:477
[0x00007f00b4ec49a0] getSingleton() /data/web/public/includes/src/__default.php:14044
[0x00007f00b4ec4848] preDispatch() /data/web/public/includes/src/Mage_Adminhtml_Controller_Action.php:160
[0x00007f00b4ec3b00] preDispatch() /data/web/public/includes/src/__default.php:13958
[0x00007f00b4ec26e0] dispatch() /data/web/public/includes/src/__default.php:18331
[0x00007f00b4ec20c0] match() /data/web/public/includes/src/__default.php:17865
[0x00007f00b4ec1a98] dispatch() /data/web/public/includes/src/__default.php:20465
[0x00007f00b4ec1908] run() /data/web/public/app/Mage.php:684
[0x00007f00b4ec17f8] run() /data/web/public/index.php:87

Lsof says:

COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
php5-fpm 24259  app   10uW  REG  202,1    82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6
php5-fpm 24262  app   10u   REG  202,1    82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6
php5-fpm 24351  app   10u   REG  202,1    82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6
php5-fpm 24357  app   10u   REG  202,1    82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6
php5-fpm 24358  app   10u   REG  202,1    82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6
php5-fpm 25563  app   10u   REG  202,1    82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6
php5-fpm 25564  app   10u   REG  202,1    82492 1220594 /data/web/public/var/session/sess_gr2clur9icgd7s2j9linag7ue6

According to strace, all these processes are waiting for flock (LOCK_EX), even the one who has the W flag in the lsof output above.

The CPU usage during this incident is near 0.

So why does the first session_start hang, even though it seems to have acquired a write lock on the session file? How could I debug this further?

Here is a discussion called "race condition with ajax and php sessions". In fact, the requests that trigger the problem above, are consistenly AJAX calls. However, this article states that:

If you've used PHP's built-in, default session handling (that uses files), you'll never come across the problem.

So currently I'm at a loss where to look next.

like image 802
Willem Avatar asked Sep 24 '14 12:09

Willem


People also ask

What does session_start () do in PHP?

session_start() creates a session or resumes the current one based on a session identifier passed via a GET or POST request, or passed via a cookie. When session_start() is called or when a session auto starts, PHP will call the open and read session save handlers.

Do I need to use session_start on every page?

It must be on every page you intend to use. The variables contained in the session—such as username and favorite color—are set with $_SESSION, a global variable. In this example, the session_start function is positioned after a non-printing comment but before any HTML.

Where should the session_start () function be used?

Note: The session_start() function must be the very first thing in your document. Before any HTML tags. As for your question you can start session wherever you want, but beware that session must be started before any output. So it is considered a reasonable approach to start session at the top of a page.

What is the use of session_start () and Session_destroy () functions in PHP?

session_destroy() function: It destroys the whole session rather destroying the variables. When session_start() is called, PHP sets the session cookie in browser. We need to delete the cookies also to completely destroy the session. Example: This example is used to destroying the session.


2 Answers

I find it best to store sessions on a local disk and not the database.

Create a directory named 'sessions' at the root directory, and then have all of your sessions write there by putting the following code at the top of scripts right before you call "session_start()"

$session_path = $_SERVER['DOCUMENT_ROOT']; //this session path assumes you are not using a subdomain
ini_set('session.save_path', $session_path.'/sessions/');

Loading from file is faster than loading from a database. And php manages it all the same, so I opt for speed.

like image 132
skidadon Avatar answered Sep 29 '22 13:09

skidadon


Something unknown is blocking the first script, and it is blocking the rest.

PHP keeps the session file open for writing until after the script terminates. That means if a script gets stuck or caught up doing something slow, all other requests dependent on the session will be blocked until it finishes.

Two best practices - don't start the session until you need it, and explicitly end the session with session_write_close() when you're done changing it, especially before doing something slow or potentially buggy.

Then you'll only have 1 stuck process, instead of a locked out user.

like image 26
Dirigible Avatar answered Sep 29 '22 12:09

Dirigible