4

This general topic has come up before, here, here, here, and no doubt elsewhere on the internet as well. In my case, unlike these, the hang arises from a blocking socket that never gets a message, and perhaps that's why the solutions described there haven't worked for me. I'm developing in tandem a C++ app which communicates with the php script via a local socket connection, and when the C++ app crashes, it leaves the php script's socket waiting for a message that never comes. I've tried using session_destroy and session_unset (calling these first in a script before session_start) but they don't work; even quitting and restarting the browser doesn't help. I can only stop the session if I remove the session_start, reload the script and then end the session via the client. How can I kill the session without having to go through that?

Edit: I forget to mention, I also tried to time the socket out with

socket_set_option($socket,0, SO_RCVTIMEO, array("sec"=>1, "usec"=>0));

But I got an 'invalid operation' error, and it didn't work.

Edit 2: Setting a manual timeout, following the tip here, worked well enough. I still don't know how to, in general, kill a session that's e.g. stuck in an infinite loop, but oh well.

Community
  • 1
  • 1
Matt Phillips
  • 9,465
  • 8
  • 44
  • 75
  • ok, now with the value 1 i don't know, what the problem is :) – Florian Apr 24 '11 at 16:15
  • @levu It looks like the option isn't even getting set. Can you not set SO_RCVTIMEO for a local socket? I don't see what's wrong with my syntax there. '0' as protocal works for socket_create. – Matt Phillips Apr 24 '11 at 16:51

2 Answers2

3

How can I kill the session without having to go through that?

The problem you're having isn't one that will be solved by killing the session.

the hang arises from a blocking socket that never gets a message

If you're using the default PHP session handler, that means that PHP is holding a lock on that file. No other PHP process is going to be able to manipulate the session as long as that lock exists.

You have a few options here.

First, consider implementing you own session save routines, which means you'd completely control whether or not there is any sort of lock on the session data. You can simply not include any locking at all, which will permit the running-but-hung PHP script to continue running in peaceful bliss. This is the most complex option.

Second, are you sure that the long-running socket script needs to write session data? If not, you can simply end the session early and release the lock by calling session_write_close. This will release the lock, though it won't actually end the long-running script when the socket closes.

Third, look at using socket timeouts in your long-running script. I'm not sure what exact method you're using to work with sockets here and have very little experience working with them in PHP, so I can't make a specific function recommendation.

Charles
  • 50,943
  • 13
  • 104
  • 142
  • To test your idea, I used a different file for the local socket--/tmp/sock1 instead of /tmp/sock. This file is new so php couldn't be holding a lock on it. It still hung, and in fact never got to that point--it hangs on the first line of login.php, which is session_start. – Matt Phillips Apr 24 '11 at 16:08
  • @Matt, the lock is on the *session* file. `session_start` blocks waiting for the lock to release. – Charles Apr 24 '11 at 16:10
  • @Charles Ok thanks, I am very new to php as is probably obvious at this point. :) session_write_close is also not working, only restarting the browser. – Matt Phillips Apr 24 '11 at 16:24
  • @Matt, so adding `session_write_close` to the long-running script after getting the session data that you need but before working with the socket isn't releasing the lock? (Adding it to other scripts does nothing here -- you need it in the long-running script so it will release the lock.) – Charles Apr 24 '11 at 16:26
  • @Charles, what can I say? I put session_write_close at the top of every php script I use, deleted session_start so I could run each one without them hanging, but when I put the session_starts back in, it hung at login.php. – Matt Phillips Apr 24 '11 at 16:55
  • @Charles Timing out my socket seems like a good way to go, but see my edit--it won't set the option. Know what I'm doing wrong there? – Matt Phillips Apr 24 '11 at 16:57
  • @Matt -- `session_write_close` should *only* go inside the single long-lived script *before* it begins working with the socket. It does not belong in *any* of the other scripts. Unfortunately I've never worked with PHP sockets, so I can't help you there. – Charles Apr 24 '11 at 17:35
  • @Charles, I put it in every script, so I must have put it in the long-lived one. I'm going to try a while loop with a non-blocking socket along the lines described here http://stackoverflow.com/questions/389645/php-how-to-set-a-timeout-on-socket-read, wish me luck (and let me know if you think of anything else!). :) – Matt Phillips Apr 24 '11 at 17:51
1

Maybe you can give a timeout to the socket? e.g. socket_select has a timeout parameter.

The value of 1000s as timeout may be too high, because apache may have killed the process before (see max_execution_time in php.ini)

Florian
  • 3,145
  • 1
  • 27
  • 38