Issues

ZF-7520: fsocken does not implement a timeout in Zend_Queue_Stomp_Client_Connection

Issue Type:

Bug

Created:

2009-08-07T10:54:06.000+0000

Last Updated:

2012-11-20T20:53:28.000+0000

Status:

Closed

Fix version(s):

Reporter:

Dheeraj Saxena (kkarank)

Assignee:

None

Tags:

Zend_Queue

Related issues:

Attachments:

Description

The Fsockopen function does not currently implement a timeout which means that if the broker is down then queue->send results in php timeout. I have gone through the code and it does'nt look like there is any other config parameter that can take care of this. I had to manually add a timeout parameter to the fsockopen call to make queue->send work (throw an exception) in case the ActiveMq broker was not running

Fatal error: Exception thrown without a stack frame in Unknown on line 0

Posted by Daniel Lo (danlo) on 2009-08-08T10:14:39.000+0000

Could you provide more information about the bug you have received? And if possible, please provide the get_ini('default_socket_timeout') setting.

-daniel

Posted by Dheeraj Saxena (kkarank) on 2009-08-08T11:31:05.000+0000

Thats strange,

The code I am seeing in 1.9 RC1 distro is

....
$this->_socket = fsockopen($str, $port, $errno, $errstr,10);
// the code below is all the same
if ($this->_socket === false) {
// aparently there is some reason that fsockopen will return false
// but it normally throws an error.
require_once 'Zend/Queue/Exception.php';
throw new Zend_Queue_Exception("Unable to connect to $str; error = $errstr ( errno = $errno )");
}

the fsockopen call is not inside a try/catch so I am not sure how the exception is being thrown? The code does not get to the point where it can check if the socket is open and is a valid resource.

Anyways, default_socket_timeout is set to 60 secs in my php.ini and the page making the request to my broker times out after that. All fine and dandy there.

The problem is that
a) while 60 secs timeout maybe valid for a webpage it is IMHO on the higher side for talking to a broker whose only job is to accect a message and put it on a queue. if it is down it is down and i am not aware of any application that can bring figure out that a broker is down and then bring it back up cleanly within 60 secs.
b) I could make a manual call to set smaller timeout through default_socket_connection but the way I have coded my logic - if the broker is down then i dehydrate my data onto the filesystem and db and that leg of the transaction has its own latency. Of course, once the broker times out I could set another timeout before commencing the dehydration process but all that is too much hackery i think.

I have reported this as a minor issue as it is not the end of the world if fsockopen can not be invoked using a custom timeout but if it can be then it would save a lot of working around.

then following line which checks if ( $this->socket === false ) will then throw the exception.

--

In regards to the request for a "driverOptions" open_timeout I don't see any problem about this. I will check with Justin first and then code it if he is happy about the idea.

Posted by Daniel Lo (danlo) on 2009-08-09T18:47:36.000+0000

This turned out to be much more of a bigger change than I thought.

I sent an email to zf-contributors requesting help as solving this problem would involve changing the API for the "best" solution and the least best solution "a patch" would involve making a static class variable in Zend_Queue_Stomp_Client_Connection.

Below is the email I sent to zf-contributors

Hello,

Someone recently brought to my attention that fsockopen's dependency on get_ini('default_socket_timeout') was really inconvenient in a web application because it is 60 seconds by default. ( http://www.php.net/manual/en/ini.list.php )

I thought about it, and I agreed that this was probably unreasonable and should allowed to be set in some manner via a configuration setting.

However, implementing this change has become fairly difficult because of the "depth" of the final class that needs to be modified.

Zend_Queue is a class that returns a Zend_Queue + an adapter attached on. The adapter in this question is Activemq. However, Activemq uses Stomp (a simple protocol for messaging), but the Stomp uses another class for actually doing the connection IO.

In eagle hindsight, I should have made the "connection" options an associative array for several of the constructor calls instead of using open($scheme, $host, $port...). Does anyone have any suggestions for fixing this that don't involve an API change, which I understand is verbotten between minor revisions.

This saves me from disrupting a large section of code to implement a minor "useful" change, but I don't like this idea of setting a "singleton" -in effect, global configuration variable. Then in Zend Frameworks 2.0 - fix this flaw, which
should allow API changes.

Does anyone know a better solution?

-daniel

Posted by Daniel Lo (danlo) on 2009-09-20T17:05:19.000+0000

From the response I got back, I think implementing static functions or updating the manual (Zend_Queue) so that the ini_setting is set properly is the best method.

Posted by Rob Allen (rob) on 2012-11-20T20:53:28.000+0000

Bulk change of all issues last updated before 1st January 2010 as "Won't Fix".

Feel free to re-open and provide a patch if you want to fix this issue.