If you are familiar with programing languages like VB.NET, you know there is something name Shared-Memory which is shared between different instance of application. My question is :Are session variables behave the same in PHP or not?
Assume this scenario:
I click twice on a link in my web-site (Both requests are sent with same headers, same cookies but in different times). $_SESSION['num'] is set to 0 and now:
On 12:00:00.01 first request is received by the server
On 12:00:00.03 first request starts its session
On 12:00:00.04 second request is received by the server
On 12:00:00.05 second request starts its session.
On 12:00:00.06 first process adds 10 to value of $_SESSION['num'].
On 12:00:00.07 second process adds 10 to value of $_SESSION['num'].
On 12:00:00.09 both processes are finished.
Now , there are two possible answers:$_SESSION['num'] is 10 or $_SESSION['num'] is 20. Which one is the answer?
The usual answer to your uestion is "what happened when you tested it?"
PHP will store your sessions wherever you tell it to store the sessions: files, shared memory, a database. By default it uses files. The session is retrieved from storage when you call session_start() it is written back to storage when you call session_write_close(), or the script exits.
If your session handler acquires a lock on the storage, then the second instance will be blocked until the first instance writes back the changes. The default files handler acquires locks.
Related
Background:
I am trying to write a script that connects on a regular basis to a web server and checks if some information on a specific page was changed. I already got this working using a combination of bash (for scripting), curl (for the actual connection) and crontab (for the scheduling).
Since the server requires authentication, I first used curl to do a POST request on the login page with my credentials and saved the cookie file (containing the PHPSESSID). Now i can use the cookie file when doing the request for the actual web page I want to check.
Question(s):
When does the server actually clear the PHPSESSID i set with my first request? I imagine it must do this sometime, otherwise it would crash because it keeps storing information about every single session that was ever started.
If the PHPSESSID is cleared on closing the browser is there some way i can simulate that even using curl?
It's a little more complicated than just "when it's cleared"
A session has a lifetime in PHP. The default is 24 minutes. That means that after you connect to a website, your session is valid until
You close the browser (which won't be simulated with cURL unless you just drop the cookies)
OR
24 minutes pass
Each time you load a page and the server calls session_start() that expiration time will be bumped an additional 24 minutes (technically speaking it's actually bumped 24 minutes at the end of the script execution on pages where session_start() is called).
When that cookie actually expires, your session is no longer valid, and $_SESSION will be empty on the server side. But your data is still on the server until the next time that the server performs a session garbage collection cycle to clear out expired sessions which, depending on the session handler in use on the server, may or may not actually delete your data. A bank, for example, might send the data off to an archive server in case they ever need the records.
The server removes the session after the session timeout-time has passed after the last request. This is by default 1440 seconds (24 minutes), it can be changed in php.ini file.
The session is not flushed serverside on closing the browser, the client loses his session data though, since the browser deletes his local memory of the session. But if you keep your sessionid somewhere safe you can use it later on again, if you stay within the timeout frame of course.
This is exactly how session hijackings work, they get your sessionid in some way and can then set this sessionid on their own machine and continue your session.
I am buidling some webapp and have implemented long-polling (and a command queue in my db) so my server can send commands to my cleint asynchronously, etc. The commands are encoded into json and sent over ajax calls for the client to server, and via long-polling for the server to client way.
Everything was working just fine, until I included my "Authentication module" in the ajax.php file. This module wraps the session stuff and calls session_start().
The problem is that, my long polling routine can wait up to 21 seconds before comming back to the client. During this time, the server won't run anything from the same session. It's instead executed right after the long polling ajax call returned.
I understand there's probably a restriction of only 1 thread per session at a time, and that the requests are queued up.
Now here's the question : What is the best way to address this? Is there a setting to allow several threads per sessions (3 would be fine, in my case). Or should I just send tell the client what is his SessionID (i have some sessions table in my db, to track which user is connected to which session(s)). The client could then send it along with any ajax calls so authentication module could be bypassed.
On the later option, iam afraid it open's up a bunch of security problems because of eventual session spoofing. I would need to send a "random string" to each session, to make sure you can't spoof too easily, but even then, it's not perfect...
Thanks for your awnsers :)
Nicolas Gauthier
It's a well known issue/fact that PHP locks session files for the duration of their usage in order to prevent race conditions.
If you take a look at the PHP source code, (ext/session/mod_files.c) you can see that the ps_files_open function locks the session file, and ps_files_close unlocks it.
If you call session_start() right at the beginning of your long-running script, and do not explicitly close the session file, it will be locked until the script terminates, where PHP will release all file locks during script shutdown.
While you are not using the session, you should call session_write_close to flush the session data to disk, and release the lock so that your other "threads" can read the data.
I'm sure you can imagine what would happen if the file was not locked.
T1: Open Session
T2: Open Session
...
T2: Write Data
T1: Write Data
The data written by thread 2 will be completely overwritten by thread 1, and at the same time, any data that thread 1 wanted to write out, was not available to thread 2.
morning
I have some doubts about the the way php works. I cant find the answer anywhere on books so I thought to hit the stack ;)
so here it goes:
lets assume we have one single server with php+apache installed. Here are my beliefs:
1 - php can handle one request at a time. Doesn't matter if apache can handle more than 1 thread at a time because eventually the invoked php interpreter is single threaded.
2 - from belief 1 follows that I believe if the server receives 4 calls at the same very time these calls are queued up and executed 1 at a time. Who makes the request last gets the response last.
3 - from 1 and 2 follows that if I cron-call a url corresponding to a script that does some heavy-lifting/time consuming stuff I slow down the server up to the moment the script returns.
Whats true? whats false?
cheers
My crystal ball suggests that you are using PHP sessions and you have having simultaneous requests (either iframes or AJAX) getting queued. The problem is that the default session handler uses files and session_start() locks the data file. You should read your session data quickily and then call session_write_close() to release the file.
I see no reason why would PHP be not able to handle multiple requests at the same time. That said, it may be semi-true for handling requests of single client, depending on the type of script.
Many scripts use sessions. When session_start() is called, session is being opened and locked. When execution of script ends, session is being closed and unlocked (this can be done manually). When there are multiple requests for the same session, first requests opens and locks session, and the second request has to wait until session is unlocked. This might make an impression that multiple PHP scripts cannot be executed at the same time, but that's true (partly) only for requests that use the same session (in other words - requests from the same browser). Requests from two clients (browsers) may be processed parallelly as long as they don't use resources (files, DB tables etc) that are being locked/unlocked in other requests.
I need to perform an action after a session times out. However I have no clue how to trigger that action without an incoming request. An event handler/a listener/a timer would suit perfect but since PHP does not support such a thing it is really difficult to accomplish what I want.
After lot of searching I bumped into session_set_save_handler but I still cannot fully understand how this method works. If I write code that triggers the action inside the close method when it will be executed?
I also need to keep the current session solution as it is and I wonder what the ramifications of using session_set_save_handler in conjunction with that will be? (My current solution sets a session cookie, assigns a name to the session and starts the session, when the user logs out or a request is done after the session timeout (that value is set in a configuration file) the session is completely destroyed)
Regards!
This is somewhat difficult to do in php, AFAIK.
But you can try by making a passive session handler:
Store session ids associated with a timestamp.
Each time the user associated with certain id makes a request, refresh it's timestamp.
You can detect defunct sessions by comparing the system's current, and each session id's timestamps. The ones that differ above a given treshold (say 30min), are assumed to have passed away. Then you can execute your own save handlers for these session ids.
This won't work if the session end handler needs to be executed inmediately, as this process is executed each time when a request arrives (from any user), so it will depend directly on the website's traffic flow.
But you can also solve it by setting cron jobs each 15min or so. Depending on how expensive your save handlers are, seems an acceptable periodicity.
PHP needs to run in some way for PHP code to execute. Either through a user request or a cronjob.
A Session is saved to the locale storage when a PHP request finishes executing or when session_write_close() is called
This session_set_save_handler() allows you to write your own save handler.
Every time I access data in $_SESSION, Does it immediately update the session file on the disk, or just once when the process goes down? Or every n bytes of data change (flush)?
This question is not necessarily about the specific file session handler, but every handler. (Does every touch in session immediately invoke an I/O of any kind, beside the storing of a normal variable in memory).
As Matt wrote, it writes at the end of script execution by default. You can read about it here in session_write_close()
Session data is usually stored after
your script terminated without the
need to call session_write_close(),
but as session data is locked to
prevent concurrent writes only one
script may operate on a session at any
time. When using framesets together
with sessions you will experience the
frames loading one by one due to this
locking. You can reduce the time
needed to load all the frames by
ending the session as soon as all
changes to session variables are done.
It writes it and the end of the process on my setup. I made a new _ session_ write_method:
public function _session_write_method($id, $sess_data) {
var_dump(file_put_contents('/var/www/public_html/testing.txt', serialize($sess_data)));
return(true);
}
and then:
$_SESSION['foo'] = 'bar';
while(true)
I executed the script,waited a few seconds and then ran 'sudo kill' on the process id. It did not write the serialized data to the file. I ran it again without the infinite loop and I got: int(22) at the very bottom of the page and testing.txt was successfully written to and contained: s:14:"foo|s:3:"bar";";
Depends on the handler. You can write your own handler to make sure it only happens as often as you like if you want to be absolutely sure about the behavior. There are 6 callbacks used to manage session variables. The one called "write" does not have to perform any real I/O and writing the session file could wait until the call to "close". It is an implementation detail that, as I said, depends on the handler.