PHP Sessions slow down the ttfb by at least 30 seconds - php

I encountered the following problem:
I have a very simple script which forwards the user to this login script via POST:
session_start();
$_SESSION["job"] = "admin";
$_SESSION["login"] = true;
$_SESSION["email"] = "email#example.com";
$_SESSION["username"] = "example";
session_write_close(); # I added this because it was recommendet to solve my problem, which it unforunately doesn't do.
header("Location: ../home");
As soon as this script is executed everything is blocked which executes session_start(); in its script. The TTFB is always above 60s
The only fix is to restart apache via service apache2 restart every time.
My Apache2and PHP are clean installed today on an absolute fresh server, everything was configured according to the official instructions. Additionally I encounter this problem on every other server I ran my script on.
What could be a solution? I've searched the internet for days now...

As read from the above comments it seems like there is further code after the header statement since working with exit solves your issue. So that people crossing this post quickly see the solution I add this answer.
To avoid this unwanted behaviour it's a good habit to place a die or exit after the statement.

Related

PHP session_start() causes script to run indefinitely

I haven't had this problem on any other server, so I'm wondering if anyone else experienced this issue. The strange part is that the lock up happens at random - sessions will work fine for 10 minutes to an hour, then I'll make a request and I'll just see the browser waiting for reply. It never times out and I have to restart Apache2 to get sessions running.
My test.php script:
error_reporting(E_ALL);
session_start();
print_r($_SESSION);
echo 'got here';
When I get a lock up, commenting out the session_start(); shows 'got here'. So it's something to do with PHP sessions. It's setup to use files in /var/lib/php/session. Opening an incognito window doesn't help.
Potentially relevant details:
Web Server: Apache2 with Prefork
OS: CentOS 6.4 x64
HD: 5+ GB free
Memory: 10+ GB free
If you need any other info please ask!

If no activity on my site for ≈30 minutes, PHP fsockopen page times out with blank page no error messages...tried all the error reporting settings

I have a Web application/site that is hosted on IIS 8.0. The site is written using PHP 5.3, and gets its data from a connection to a database using PHP's odbc_connect() function.
On two of the pages on my site, an E-mail must be sent to the user for him or her to activate a forum post. I am currently using a home-brewed SMTP method that utilizes fsockopen() for sending the E-mails.
The problem is as follows:
If ≈30 minutes goes by during which the site is not visited by the user, and they visit the page that sends the E-mail, the page will completely time out according to PHP's max_execution_time value, with no data being sent to the user's browser (the user sees a blank page).
HOWEVER, the E-mail is still sent, and every bit of code on that page is executed! How do I know? I created a log file that gets written to at the very end of the suspect page, and it always gets written to, even though the page times out. If the user backs out of the blank page, and submits the E-mail again, it magically works!
Things I have tried, that did not change a thing:
Tried using PHP PEAR mail
Tried using PHPMailer
Tried using PHP Swift Mailer
Tried using flush()
Tried using ob_flush()
Tried increasing PHP's max_execution_time (this just make the timeout longer)
Tried using non-blocking mode on fsockopen with stream_set_blocking();
Tried using PHP 5.4 / 5.3 / 5.2
Tried setting error_reporting(E_ALL);
Tried setting ini_set("display_errors", 1);
Tried setting ini_set("display_startup_errors", 1);
All I get is a blank screen after 30 minutes of idle time, with no error messages.
Does anyone have any ideas? Remember, all the code on the page gets executed, but it seemingly never stops "processing" until it times out.
example code:
<?php
include("functions.php"); //contains "smtp_mail" and "logwrite" functions
odbc_connect($connectionstring,$username,$password);
$mail = smtp_mail($recipient, $subject, $message);
echo "made it here"; //this never makes it to the user's browser!
logwrite("made it here"); //this is always executed, but still times out!
?>
It turns out the issue resided on my host's end. I changed hosts and the code posted above works fine.

Server not running PHP script

I have a simple PHP script that is supposed to redirect to another document after running some code, like so:
if...{
$_SESSION['username'] = $_POST['username'];
$_SESSION['login_status'] = true;
header('location: index.php');
}
else{...
The script works fine on one of the servers I have tried it on but not on the other. As it seems the other server doesn't go to the 'header' row but just stops running half way. All I am left with is a blank page with the title of the previous page. Why is that? Any ideas?
The PHP version on the server that runs the script is 5.1.6, the server that doesn't 4.3.9, not that I believe that has anything to do with it.
Did you started the session? Or your server might be just misconfigured.
Read the logs.
Check from php settings whether session.auto_start is enabled.
Also, it might be that older version of PHP doesn't know how to parse the location: ... string.
So change it to uppercase (so it conforms to HTTP specification):
header('Location: index.php')
Run your code with error reporting, so that you will get some clue about the error
error_reporting(E_ALL);
See PHP Error reporting

Getting PHP processing to happen in the background

I am working on a PHP website, and I am moving it over to a new server. The new server I am moving to does not have CRON compatibility. To compensate for this I have devised a system using time formats and database tables and more to run my code instead.
What I am having a problem with is this bit of code:
if ($lasttime < $pretime)
{
$newtime = strtotime("now");
queryMysql("UPDATE time SET time=".$newtime." WHERE time=".$lasttime);
include_once 'grabber/grabber.php';
}
Specifically it's the include_once 'grabber/grabber.php'; which is causing the problem. When the timer comes round and this code runs, it gets to the include and then the code stops, with no error provided, so the include fails. I have tried changing it to an exec() but to be honest I don't completely understand how exec() works and if it is the correct thing to do. This is how I used it:
if ($lasttime < $pretime)
{
$newtime = strtotime("now");
queryMysql("UPDATE time SET time=".$newtime." WHERE time=".$lasttime);
$grabber = $base."grabber/grabber.php";
exec($grabber);
}
This does not stop the code and seems to run but it doesn't actually work, if grabber/grabber.php runs correctly then I get an email to confirm using the PHP mail() function
If anyone could help me solve this or shed some light that would be brilliant.
Thanks.
This is most probably an issue with the file location or permissions. There should be some kind of error, or the code doesn't stop, but you don't properly check that or there is some kind of an issue with the code in grabber.php itself. Add some debugging lines - print the filename, so you can check for errors in the path/name; add error_reporting(E_ALL); ini_set('display_errors', true); somewhere above the include_once line; make sure the file is where you're trying to open it from, taking into account relative paths, etc. Make sure you have permissions to run this file.
exec() is not what you need in this case, at least not in the way that you're trying to use it.
If that doesn't help - give some more information about how you run the scripts that you've shown, what's in the grabber.php file, what errors you get, etc.
(Assuming your server is *nix) If you want to use exec() you need to place a hashbang at the top of the script that points to the PHP executable and give it execute permissions.
Or (this is probably the better/more portable approach), change
$grabber = $base."grabber/grabber.php";
exec($grabber);
to
$grabber = "php ".$base."grabber/grabber.php";
exec($grabber);
...as if you were running it from a terminal.
However, I doubt this will solve the problem - I think the answer is more likely to be one of these things:
A parse error in grabber.php. Keep in mind that there are slight syntax differences between major PHP versions - if your PHP version is different on your old/new hosts, this may be the problem.
A call to a function that was defined on your old host but not on your new host, because of a difference in PHP version or installed extensions
grabber.php was corrupted during the move between servers
Try it with the include_once, but do ini_set('display_errors',1); error_reporting(-1); to make sure you actually see any errors. How are you calling you main script? How will you see the errors? Edit the question with this info, any code from grabber.php you think may be relevant and I will expand this answer.

session_start hangs

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.
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().
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.
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.
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
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: -
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).
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;
}
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.
Just put session_write_close(); befor Session_start();
as below:
<?php
session_write_close();
session_start();
.....
?>
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"
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.
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
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.
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 .
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.

Categories