php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #59970 ack()'ing a message makes rabbitmq disconnect the server
Submitted: 2011-09-27 13:40 UTC Modified: 2013-10-15 11:54 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: marcelog at gmail dot com Assigned: pierrick (profile)
Status: No Feedback Package: stomp (PECL)
PHP Version: 5.3.3 OS: Linux gentoo
Private report: No CVE-ID: None
 [2011-09-27 13:40 UTC] marcelog at gmail dot com
Description:
------------
While connecting to a rabbitmq 2.6.1, I'm having issues when 
using 
Stomp::ack() to acknowledge the received messages.

The messages are never acknowledged and the connection to the 
server 
drops with "Unexpected EOF while reading from socket". It 
seems the 
server is closing the client connection.

Reproduce code:
---------------
The following code will break with an "Unexpected EOF while reading from socket" after receiving a couple of messages. The rabbitmq (2.6.1) seems to be disconnecting the client. 

$broker = 'tcp://127.0.0.1:61613';
$queue  = '/queue/foo';
$msg    = 'bar';

try {
    $stomp = new Stomp($broker, 'guest', 'guest');
    $stomp->subscribe('/queue/commands');
    while(true) {
        if ($stomp->hasFrame()) {
            $frame = $stomp->readFrame();
            if ($frame !== false) {
                $stomp->ack($frame);
                var_dump($frame);
            }
        }
    }
    $stomp->disconnect();
} catch(StompException $e) {
    echo $e->getMessage();
}

The messages are sent in a transaction with another php script, by using Stomp::begin() and Stomp::commit(). No problems there.

After debugging a little, I ended up in FRAME_HEADER_FROM_HASHTABLE(h, p) in php_stomp.c.

It seems that stomp_ack() populates the headers in the ack message with the same headers that came with the original message. The conflicting header that triggers the issue seems to be "content-length". Patching FRAME_HEADER_FROM_HASHTABLE as follows seems to fix this issue (the messages are correctly flushed from the server and the client continues to be connected):

65c65,67
<                       zend_hash_add(h, string_key, strlen(string_key)+1, Z_STRVAL_PP(value), Z_STRLEN_PP(value)+1, NULL); \
---
>                       if (strcmp(string_key, "content-length") != 0) { \
>                               zend_hash_add(h, string_key, strlen(string_key)+1, Z_STRVAL_PP(value), Z_STRLEN_PP(value)+1, NULL); \
>                       } \

What I basically did is to NOT send content-length in the ack frame. I'm not sure this is the correct fix, but it seems to pinpoint the issue.


Expected result:
----------------
The messages should be acknowledged.
The client should continue to be connected to the server.
The messages should "go away" from the rabbitmq server.

Actual result:
--------------
The exception "Unexpected EOF while reading from socket" is 
thrown in stomp_recv() after a couple of (apparently) failed 
stomp_ack() calls.

The messages are kept in the rabbitmq server (the ack() calls 
are not flushing them from the server).

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-11-19 01:26 UTC] pierrick@php.net
The fix for this bug has been committed.

You can find the latest version here :
https://github.com/php/pecl-tools-stomp/downloads
 [2012-11-19 01:26 UTC] pierrick@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: pierrick
 [2013-03-17 16:44 UTC] zimt@php.net
-Status: Closed +Status: Re-Opened
 [2013-03-17 16:44 UTC] zimt@php.net
run in the same problems as original poster,
his fix worked for me, but contrary to he comment was not included
within the extension so far.

applied fix at my copy, and made pull request:
https://github.com/php/pecl-tools-stomp/pull/1
 [2013-04-18 17:00 UTC] mi+php at aldan dot algebra dot com
We saw the same problem with ActiveMQ:

https://issues.apache.org/jira/browse/AMQ-3653

ActiveMQ-5.8 seems to deal with this, but it is a good idea to fix it properly.

The provided patch modifies the macro FRAME_HEADER_FROM_HASHTABLE also used by SUBSCRIBE (at least). My version alters the frame's headers after they were copied:

--- php_stomp.c 2012-11-18 17:35:40.000000000 -0500
+++ php_stomp.c 2013-04-18 12:44:57.000000000 -0400
@@ -1110,4 +1119,12 @@
                if (Z_TYPE_P(frame_obj_prop) == IS_ARRAY) {
                        FRAME_HEADER_FROM_HASHTABLE(frame.headers, Z_ARRVAL_P(frame_obj_prop));
+                       /*
+                        * ACKs and NACKs have no body, so having a
+                        * content-length header is pointless at best.
+                        * At worst it may break interaction with some
+                        * brokers such as earlier versions of ActiveMQ
+                        */
+                       zend_hash_del(frame.headers, "content-length",
+                           sizeof("content-length"));
                }
        } else {

It is a little efficient (involves a hash-table lookup), but may be more corrrect?..
 [2013-04-25 15:29 UTC] pierrick@php.net
-Status: Re-Opened +Status: Feedback
 [2013-04-25 15:29 UTC] pierrick@php.net
Sorry about that. I thought I merged it but apparently did not. I just merged the 
pull request now.

Could you both zimt and mi+php at aldan dot algebra dot com try the git master 
version and let me know if everything work. If it does work i'll close the bug and 
do a new release of the extension.
 [2013-10-15 11:54 UTC] pecl-dev at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 31 23:01:28 2024 UTC