Skip Menu |

This queue is for tickets about the WWW-Curl CPAN distribution.

Report information
The Basics
Id: 36684
Status: resolved
Priority: 0/
Queue: WWW-Curl

People
Owner: Nobody in particular
Requestors: vlad.samara [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 4.00
Fixed in: (no value)



Subject: WWW::Curl::Multi gets same url for each handle (even if each handle was configured with its own url)
I've applied all fixes mentioned here in bug database to make ::Multi fetch something. But it turns out to fetch same URL for each handle (irregarding of URL each of the handles was configured for). I've run strace to see what it actually fetches - it really does send request to the same URL. I've spent 4 hours trying different combinations, nothing helps.. I've tried perl-5.10 and perl 5.8.8 (self compiled with all defaults; no threads support). This is on linux x86 (redhat 7.3 and centos 3). libcurl version tried were 7.16 and 7.8.2.
Subject: multi2.pl
#!/usr/test/perl-5.10.0/bin/perl use strict;use warnings; use WWW::Curl::Easy; use WWW::Curl::Multi; my %easy; my %easy_props; my $easy_jobs_id; my $active_handles = 0; sub _add_job { my ($url,$rvar) = @_; my $curl_id = ++$easy_jobs_id; $easy{$curl_id} = WWW::Curl::Easy->new; $easy{$curl_id}->setopt(CURLOPT_PRIVATE,$curl_id); $easy{$curl_id}->setopt(CURLOPT_HEADERFUNCTION, sub { return length($_[0]); }); $easy{$curl_id}->setopt(CURLOPT_URL, $url); $easy_props{$curl_id} = { 'data', $rvar, 'url', $url }; $easy{$curl_id}->setopt(CURLOPT_WRITEFUNCTION, sub { my $t = shift; $$rvar .= $t; return length($t); } ); } sub run_jobs { my $curlm = WWW::Curl::Multi->new; foreach ( values %easy) { $curlm->add_handle($_); $active_handles++; }; while ($active_handles) { my $active_transfers = $curlm->perform; if ($active_transfers != $active_handles) { while (my ($id,$return_value) = $curlm->info_read) { if ($id) { $active_handles--; my $actual_easy_handle = $easy{$id}; print STDERR "got content for $easy_props{$id}->{url}\n" . "${$easy_props{$id}->{data}}\n\n"; delete $easy{$id}; } else { print STDERR "info read returned $id and $return_value\n"; }; } } } } my $v1 = ''; my $v2 = ''; _add_job("http://apple.com",\$v1); _add_job("http://www.ft.com",\$v2); run_jobs();
From: vlad.samara [...] gmail.com
Another file (that is structured a little different). Same result. It seems ::Easy somehow uses the options provided for the last handle created (like stored in static variables or something)..
#!/usr/test/perl-5.10.0/bin/perl use strict; use warnings; use WWW::Curl::Easy; use WWW::Curl::Multi; my %easy; my %easy_props; my $easy_jobs_id; my $active_handles = 0; #my $curl = WWW::Curl::Easy->new; my $curlm = WWW::Curl::Multi->new; sub _add_job { my ($url) = @_; my $curl_id = ++$easy_jobs_id; my $curl = WWW::Curl::Easy->new; $curl->setopt(CURLOPT_PRIVATE,$curl_id); $easy{$curl_id} = $curl; $curl->setopt(CURLOPT_HEADERFUNCTION, sub { return length($_[0]); }); $curl->setopt(CURLOPT_URL, $url); my $data2; $easy_props{$curl_id} = { 'data', \$data2, 'url', $url }; open (my $fileb, ">", \$data2 ); $curl->setopt(CURLOPT_WRITEDATA,$fileb); $curlm->add_handle($curl); $active_handles++; } sub run_jobs { while ($active_handles) { #this is how loop that calls $curlm->perform should look like #according to bugreports in rt.cpan.org my $active_transfers = $curlm->perform; if ($active_transfers != $active_handles) { while (my ($id,$return_value) = $curlm->info_read) { if ($id) { $active_handles--; my $actual_easy_handle = $easy{$id}; # do the usual result/error checking routine here print STDERR "got content for $easy_props{$id}->{url}:\n${$easy_props{$id}->{data}}\n\n"; # letting the curl handle get garbage collected, or we leak memory. delete $easy{$id}; } else { print STDERR "info read returned $id and $return_value\n"; }; } } } } map { _add_job("http://$_"); } ('apple.com','www.ft.com'); run_jobs();
From: vlad.samara [...] gmail.com
Чтв. Июн. 12 09:23:47 2008, vladblah писал: But this works fine. May be all ::Easy objects need to be pre-created, and only then they can be configured (urls set etc)?
#!/usr/test/perl-5.10.0/bin/perl use WWW::Curl::Easy; use WWW::Curl::Multi; use warnings; use strict; my %easy; my $c1 = new WWW::Curl::Easy; my $c2 = new WWW::Curl::Easy; $easy{1} = $c1; $easy{2} = $c2; my ( $header, $body, $header2, $body2 ); sub header_callback { my $chunk = shift; $header .= $chunk; return length($chunk); } sub body_callback { my ( $chunk, $handle ) = @_; $body .= $chunk; return length($chunk); } sub header_callback2 { my $chunk = shift; $header2 .= $chunk; return length($chunk); } sub body_callback2 { my ( $chunk, $handle ) = @_; $body2 .= $chunk; return length($chunk); } $c1->setopt(CURLOPT_URL, 'http://www.ft.com'); $c1->setopt(CURLOPT_PRIVATE, 1); $c1->setopt( CURLOPT_HEADERFUNCTION, \&header_callback ); $c1->setopt( CURLOPT_WRITEFUNCTION, \&body_callback ); $c2->setopt(CURLOPT_URL, 'http://www.apple.com'); $c2->setopt( CURLOPT_HEADERFUNCTION, \&header_callback2 ); $c2->setopt( CURLOPT_WRITEFUNCTION, \&body_callback2 ); $c2->setopt(CURLOPT_PRIVATE, 2); my $active_handles = 0; my $curlm = new WWW::Curl::Multi; $curlm->add_handle($c1); $active_handles++; $curlm->add_handle($c2); $active_handles++; while ($active_handles) { my $active_transfers = $curlm->perform; if ($active_transfers != $active_handles) { while (my ($id, $return_value) = $curlm->info_read) { if ($id) { $active_handles--; print "return_value = $return_value id $id\n"; } } } #print "info_read: " . $curlm->info_read . "\n"; #print "speed: " . $curl->getinfo(CURLINFO_SPEED_DOWNLOAD) . "\n"; #select(undef, undef, undef, 0.05); } $c1->cleanup; $c2->cleanup; print "body1 $body\n\n\nbody2 $body2\n"; exit(0);
I'm sorry, but I can't reproduce this at all. All three versions return the proper output for me. I've tried all combinations of libcurl 7.12, 7.18 and perl 5.10, 5.8.8. Would you try 4.01 though, to see if it fixes this issue for you? I've just released it.