PHP Garbage Collector Keeps Removing My Sessions - php

The Problem:
I have a website that uses PHP sessions to allow users to log in. It works fine. But the session expires too soon that 1 minute of inactivity will log out the user.
My Environment:
Php version: 7.1
Server: NGINX
Framework: CakePHP 3.5
What I did so far?
I did every single solution on the StackOverflow or any search result I get. I extended my session timeout both in php.ini and CakePHP configurations.
The solution
After 2 or 3 days of research, I found the solution. In my php.ini I found a configuration named session.gc_probability and I put value 0 for that. Now my sessions never get expired except if the user logs out intentionally.
And now my current problem is, I don't want my session.gc_probability configuration to be zero as it will not collect any garbage (Not really sure about this. Please correct me if this information is wrong.). And this will cause the sessions to remain for month or years which a real GARBAGE for the server.
I got the idea of giving session.gc_probability zero value from here
session.gc_divisor coupled with session.gc_probability defines the
probability that the gc (garbage collection) process is started on
every session initialization. The probability is calculated by using
gc_probability/gc_divisor, e.g. 1/100 means there is a 1% chance that
the GC process starts on each request. session.gc_divisor defaults to
100.
What is exactly wrong with my configurations? What causes the garbage collection to remove my sessions that soon? session.gc_probability was 1 and session.gc_divisor was 1000. I think a process with 1/1000 probability should not start every 1 or 2 minutes.

According to your follow-up comments your setting for Session.handler is php. The Sessions documentation explains:
The built-in configurations are:
php - Saves sessions with the standard settings in your php.ini file.
cake - Saves sessions as files inside tmp/sessions. This is a good option when on hosts that don’t allow you to write outside your
own home dir.
[…]
The default php.ini setting for session.save_path depends on your PHP distribution (and it can be changed anyway) but it normally involves a shared data storage for all PHP applications that do not opt out. That means that the app with the shortest session.gc_maxlifetime is likely to remove session data from other apps.
Switching to cake should address that.
A little follow-up about session.gc_probability and session.gc_divisor. Setting them too aggressively will cause frequent garbage collection. That may harm performance but it won't cause premature data expiration. On the other side, too loose values will still allow access to obsolete data.

Related

AWS Elastic Beanstalk PHP installation - session time out

I've observed that my PHP pages in the production environment session times out but unable to figure out what determines the duration of time out.
I use AWS ElasticBeanstalk to run the PHP code.
I'd like to find out
what is the session time set to and where is it set typically?
how I can programmatically control the time out from the PHP layer
Thanks in advance
If the session timeout is not explicitly set through the code, then you can check the default value set in the php.ini file for session.gc_maxlifetime which specifies the number of seconds after which data will be seen as 'garbage' and potentially cleaned up. Garbage collection may occur during session start (depending on session.gc_probability and session.gc_divisor). Defaults to 1440 (24 minutes).
References:-
session.gc_maxlifetime
PHP - How to implement session lifetimes

How to configure PHP for automatical regular removing of session data / sess_ files?

The PHP session data is stored on the server side in sess_{$hash} files in the directory defined in the session.save_path setting of php.ini.
If my understanding is correct, these files should get removed after a defined period of time. How to get and how to set this time? I tried settings session.cache_expire and session.gc_maxlifetime. E.g. I set session.cache_expire to 2 (minutes), but after two minutes the files are still there. I also set session.gc_maxlifetime to 120 (seconds). But this also didn't work.
How to configure PHP to get the sess_* files being removed after a defined period of time?
The session.gc_maxlifetime is what defines when sessions data is marked for garbage collection (not necessarily when it's deleted). The actual deletion of that data depends on a number of variables. Most prominently the session.gc_probability and session.gc_divisor. The probability over the divisor determine the chance that the session initialization process will invoke the garbage collector to clean up marked garbage. By default they are 1 and 100, respectively (meaning there is a 1% chance the garbage collector will clean up).
This is PHP's default mechanism for garabage collection of session data. However, on some systems (most notably Ubuntu) the default session GC is replaced by an external cleanup mechanism which is implemented as a cron job that runs regularly to clean up session files based on stat calls and the session.gc_maxlifetime.
You tend not to notice these side effects on a busy site, as the number of session_start() calls increase, the probability that stale session data is regularly cleaned up increases. However, on a low traffic site (namely your development environment) this probability drops significantly enough that you might notice stale session data hanging around for a while. This is typically not something to be concerned with. As long as you are deleting the session cookie and regularly using session_destroy() when the session needs to be deleted, this is all moot.

Is session.gc_maxlifetime still based on last modified date?

According to this answer, the session.gc_maxlifetime is based (as of PHP 4.2.3) on the last modified date of the session:
Note: If you are using the default file-based session handler, your filesystem must keep track of access times (atime). Windows FAT does not so you will have to come up with another way to handle garbage collecting your session if you are stuck with a FAT filesystem or any other filesystem where atime tracking is not available. Since PHP 4.2.3 it has used mtime (modified date) instead of atime. So, you won't have problems with filesystems where atime tracking is not available.
I can find nothing on the official documentation about that, the note seems to be disappeared, so is this still true?
The right answer is yes(PHP 5 - PHP 8), it based on last modified time.
And if php script read session variable, php runtime will update modified time.
The c souce is here (PHP 7.3 C Source):
No, session.gc_maxlifetime worksby time interval defined.
This value (default 1440 seconds) defines how long an unused PHP session will be kept alive. For example: A user logs in, browses through your application or web site, for hours, for days. No problem. As long as the time between his clicks never exceed 1440 seconds. It's a timeout value.
PHP's session garbage collector runs with a probability defined by session.gc_probability divided by session.gc_divisor. By default this is 1/100, which means that above timeout value is checked with a probability of 1 in 100.

Apache session works differently on the same server

The situation is we have a local server machine with Apache on it, and two projects on the same local server.
The problem is when we set up session.gc_maxlifetime = 10, for example, the server logs out on project N1 after 10 seconds with deleting the session file successfully, but on the other project N2, the session files are not deleted and the session is not logged out.
session.gc_probability and session.gc_divisor are both set up to 1.
What could be the reason of that?
Thanks.
It could be because of PHP garbage collector, which may or not remove sessions after desired period of time. See explanation:
http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime
session.gc_maxlifetime specifies the number of seconds after which
data will be seen as 'garbage' and potentially cleaned up. Garbage
collection may occur during session start (depending on
session.gc_probability and session.gc_divisor).
(Emphasis mine)

Using Xampp, php's session timeout doesn't work

I tried to change the value of session.gc_maxlifetime in php.ini to a small value so I could check if the session timeout was working or not, but the session never seems to expire. I also restarted apache to reload the php.ini.
Does anyone know what can be the cause ?
The directive is called session.gc_maxlifetime and the gc prefix provides a little hint on how it works: PHP includes a built-in garbage collection process that takes care of physically removing obsolete session data from disk. But that process is not launched on every PHP request because that'd be an unnecessary overhead (even a single HTML document can trigger the execution of some dozen PHP scripts). Instead, it's executed randomly. That's controlled by the two other directives that start with "gc_":
session.gc_probability
session.gc_divisor
Quoting from the manual:
session.gc_divisor coupled with session.gc_probability defines the
probability that the gc (garbage collection) process is started on
every session initialization. The probability is calculated by using
gc_probability/gc_divisor, e.g. 1/100 means there is a 1% chance that
the GC process starts on each request.
All this means that you cannot really know whether session.gc_maxlifetime is being honoured until the process runs. And if you're testing it in your local development box the process will run very few times (unlike your live server where there're thousand hits per minute).
A quick way to force it is to make gc_probability equal to gc_divisor so probability becomes 1.

Categories