Subject: | Does not process data if a negotiating command comes before data bucket |
Was not getting callback to the data sub as expected.
Using the perl debugger, I found that the serverclient hybrid object had a databucket of this:
'_databucket' => ARRAY(0x870bbc8)
0 HASH(0x87179a0)
'data' => 'EN'
'realdata' => 0
1 HASH(0x8717a48)
'data' => HASH(0x842813c)
So the first item in the array was a command and the second was a complex hash. However,
the 2nd item was not being processed.
I think this is due to the databucket array ref being changed during the foreach loop. This is
the patch that fixes it:
--- EasyTCP.pm.original 2007-12-13 12:28:43.287165224 +0000
+++ EasyTCP.pm 2007-12-13 12:55:05.450675792 +0000
@@ -842,7 +842,9 @@
#
# Process all this client's data buckets
#
- foreach (@{ $serverclient->{_databucket} }) {
+ # Save a copy of the data into @_ because it could be
+ # amended if an internal negotiating command comes in before normal
data
+ foreach (@_ = @{ $serverclient->{_databucket} }) {
if ($_->{realdata}) {
#
I found that you need to save off the databucket before you can iterate through it. As the
first item is a command which calls _serverclient_negotiate, this attempts to read some data
via $client->data(). This method does a shift on {_databucket}. However, this then causes the
next iteration of the foreach to bypass the 2nd item.
I've attached a small perl program to demonstrate what is happening. You would expect
output of "this\nold\nman", but due to the shift, this misses out the 2nd item, which is
effectively what is happening within EasyTCP.
I thought a @{ $array_ref } copied the data temporarily, but I guess it just dereferences it.
Ton
Subject: | changing_array.pl |
#!/usr/bin/perl
use warnings;
use strict;
my $a;
$a = [qw(this old man)];
print "Without copying\n";
foreach my $i (@{$a}) {
print $i,$/;
shift @$a;
}
$a = [qw(this old man)];
print "Copied away first\n";
foreach my $i (@_ = @{$a}) {
print $i,$/;
shift @$a;
}