31

since a few hours our server hangs every time you do a session_start.

For testing purposes i created a script which looks like this:

<?php
session_start();
?>

Calling it from the console hangs and it can't even be stopped with ctrl-c, only kill -9 works. The same for calling it via Apache. /var/lib/php/session/ stays empty but permissions are absolutely fine, www can write and also has read permissions for all parent folders.

According to the admins there were no changes made on the server and there is no special code registered for sessions. The Server is CentOS 4 or 5 and yesterday everything was working perfectly. We rebooted the server and updated PHP, but nothing changed.

I've ran out of ideas, any suggestions?

UPDATE

We solved this problem by moving the project to another server, so while the problem still exists on one server there is no immediate need for a solution anymore. I will keep the question open in case someone has an idea for others having a similar problem in the future, though.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • Check the system error logs - Is there enough space? Are your logfiles not overflowing? Are you not running out of inodes? Is there some limit on number of files in /tmp/session, or wherever you store your files? – Piskvor left the building Dec 02 '10 at 09:00
  • The logfiles show no error and the storage is on an NFS. Another server accessing the same NFS works for the project. There is no limit on the number of session files. –  Dec 02 '10 at 09:23
  • Connection between server A to NSF is questionable. Check the connection again. – ajreal Dec 02 '10 at 09:42

12 Answers12

27

There are many reasons for that, here are a few of them:

A. The session file could be opened exclusively. When the file lock is not released properly for whatever reason, it is causing session_start() to hang infinitely on any future script executions. Workaround: use session_set_save_handler() and make sure the write function uses fopen($file, 'w') instead of fopen($file, 'x')

B. Never use the following in your php.ini file (entropie file to "/dev/random"), this will cause your session_start() to hang:

<?php
ini_set("session.entropy_file", "/dev/random");
ini_set("session.entropy_length", "512");
?>

C. session_start() needs a directory to write to.

You can get Apache plus PHP running in a normal user account. Apache will then of course have to listen to an other port than 80 (for instance, 8080).

Be sure to do the following things: - create a temporary directory PREFIX/tmp - put php.ini in PREFIX/lib - edit php.ini and set session.save_path to the directory you just created

Otherwise, your scripts will seem to 'hang' on session_start().

Thariama
  • 50,002
  • 13
  • 138
  • 166
  • 1
    After rebooting there shouldn't be any locks left and `lsof` showed no other running PHP scripts. We didn't change entropy file or length. The path for the session exists and is writeable, so C doesn't seem to be it either. We moved the project to another node which has identical configuration and it works there again. Thanks for the reply but it doesn't seem to be the problem. –  Dec 02 '10 at 09:22
  • Try using a custom non-file based session handler. – symcbean Dec 02 '10 at 12:37
  • 2
    can you give more details on option A? – danielson317 May 28 '15 at 22:41
6

If this helps:

In my scenario, session_start() was hanging at the same time I was using the XDebug debugger within PHPStorm, the IDE, on Windows. I found that there was a clear cause: Whenever I killed the debug session from within PHPStorm, the next time I tried to run a debug session, session_start() would hang.

The solution, if this is your scenario, is to make sure to restart Apache every time you kill an XDebug session within your IDE.

Dan Nissenbaum
  • 13,558
  • 21
  • 105
  • 181
3

Ok I face the same problem on 2 PC, 1 is MAC mini XAMPP, 1 is Windows 10 Xampp. Both is php spent infinity to run session_start(). Both PHP version is 7.x.x

I found that session files is lock to read and write. So that I added code to make PHP read session files and immediately unlock when done with

<?php
session_start([
    'read_and_close' => true,
]);
?>

or

<?php
//For PHP 5.x
session_start();

session_write_close();
?>

After this PHP unlock session file => Problems solve

minhhq
  • 444
  • 5
  • 9
3

I had a weird issue with this myself.

I am using CentOS 5.5x64, PHP 5.2.10-1. A clean ANSI file in the root with nothing other than session_start() was hanging. The session was being written to disk and no errors were being thrown. It just hung.

I tried everything suggested by Thariama, and checked PHP compile settings etc.

My Fix:

yum reinstall php;  /etc/init.d/httpd restart

Hope this helps someone.

To everyone complaining about the 30 seconds of downtime being unacceptable, this was an inexplicable issue on a brand new, clean OS install, NOT a running production machine. This solution should NOT be used in a production environment.

Nick B
  • 487
  • 4
  • 8
  • @Wimpie reinstalling php and restarting httpd takes about 30 seconds even on a low-grade VPS. – csvan Jun 16 '15 at 12:34
  • @csvan that's exactly 30 seconds of unacceptable downtime – Kapitein Witbaard Jul 14 '15 at 10:13
  • @KapiteinZeiksnor 30 seconds of unacceptable downtime which you easily mitigate by showing visitors a message saying that you are doing emergency maintenance and will be back in 30 seconds. – csvan Jul 14 '15 at 14:13
  • @KapiteinWitbaard If you're seeing this particular issue, you're already dead in the water. – Nick B Feb 26 '16 at 20:04
  • 1
    @csvan 30 seconds may be acceptable when your website is not making any money. When you're taking 10,000 orders an hour at an average of 65 dollars, then 30 seconds, or $5417 is absolutely unacceptable. When you're customer service are the only people affected by this particular error and your customers are still ordering, then no, you're not already dead in the water. This fix may work for your blog, but it's not going to work for my ecommerce site. – capitalaudience.com May 08 '16 at 17:47
2

The problem: -

Iv experienced (and fixed) the problem where file based sessions hang the request, and database based sessions get out of sync by storing out of date session data (like storing each session save in the wrong order).

This is caused by any subsequent request that loads a session (simultaneous requests), like ajax, video embed where the video file is delivered via php script, dynamic resource file (like script or css) delivered via php script, etc.

In file based sessions file locking prevents session writing thus causing a deadlock between the simultaneous request threads.

In database based session the last request thread to complete becomes the most recent save, so for example a video delivery script will complete long after the page request and overwrite the since updated session with old session data.

The fix: -

If your ajax or resource delivery script doesnt need to use sessions then easiest to just remove session usage from it.

Otherwise you'd best make yourself a coffee and do the following: -

  1. Write or employ a session handler (if not already doing so) as per http://www.php.net//manual/en/class.sessionhandler.php (many other examples available via google search).
  2. In your session handler function write() prepend the code ...

        // processes may declare their session as read only ...
        if(!empty($_SESSION['no_session_write'])) {
                unset($_SESSION['no_session_write']);
                return true;
        }
    
  3. In your ajax or resource delivery php script add the code (after the session is started) ...

        $_SESSION['no_session_write'] = true;
    

I realise this seems like a lot of stuffing around for what should be a tiny fix, but unfortunately if you need to have simultaneous requests each loading a session then it is required.

NOTE if your ajax or resource delivery script does actually need to write/save data, then you need to do it somewhere other than in the session, like database.

user229044
  • 232,980
  • 40
  • 330
  • 338
ekerner
  • 5,650
  • 1
  • 37
  • 31
2

Just put session_write_close(); befor Session_start();

as below:

<?php
    session_write_close();
    session_start();
    .....
?>
2

I don't know why, but changing this value in /etc/php/7.4/apache2/php.ini worked for me:

;session.save_path = "/var/lib/php/sessions"
session.save_path = "/tmp"
Edward van Kuik
  • 1,357
  • 1
  • 9
  • 9
1

To throw another answer into the mix for those going bananas, I had a session_start() dying only in particular cases and scripts. The reason my session was dying was ultimately because I was storing a lot of data in them after a particularly intensive script, and ultimately the call to session_start() was exhausting the 'memory_limit' setting in php.ini.

After increasing 'memory_limit', those session_start() calls no longer killed my script.

Daydream Nation
  • 326
  • 3
  • 7
0

For me, the problem seemed to originate from SeLinux. The needed command was chcon -R -t httpd_sys_content_t [www directory] to give access to the right directory. See https://askubuntu.com/questions/451922/apache-access-denied-because-search-permissions-are-missing

Community
  • 1
  • 1
0

If you use pgAdmin 4 this can happen as well.

If you have File > Preferences > SQL Editor > Options > "Auto Commit" disabled, and you just ran a query using the query tool but didn't manually commit, then session_start() will freeze.

Enable auto commit, or manually commit, or just close pgAdmin, and it will no longer freeze.

Andrew
  • 18,680
  • 13
  • 103
  • 118
0

In my case it seems like it was the NFS Share that was locking the session , after restarting the NFS server and only enabled 1 node of web clients the sessions worked normally .

Mawardy
  • 3,618
  • 2
  • 33
  • 37
0

Yet another few cents that might help someone. In my case I was storing in $_SESSION complex data with several different class objects in them and session_start() couldn't handle the whole unserialization as not every class was loaded on session_start. The solution is my case was to serialize/jsonify data before saving it into the $_SESSION and reversing the process after I got the data out of session.

J. Wrong
  • 822
  • 11
  • 10