-2

I'm creating a script with thread so I had to rebuild perl (perl5.20) with threads support. Since I have rebuild perl, I have an error :

Can't locate object method "query_form" via package "LWP::UserAgent"

I've tried to re-install LWP::UserAgent, LWP::Simple, URI, but they are up-to-date(according to cpan).

The faulty code :

#!/usr/bin/env perl

package get_xml;

use strict;
use warnings;
use Curses;
use LWP::Simple;
use LWP::UserAgent;
use MIME::Base64;
use URI;
use URI::http;
use HTTP::Request::Common;
use parse_xml;

# ...

sub write_conv_thread{
    my ($window, $rows, $username, $url, $ua) = @_;
    while(1){
        $$url->query_form(  # line 43
            "heartbeat" => '0',
            "conv"      => 0,
            "username"  => "$username",
            "active"    => 0
        );
        my $xml = $$ua->get($url);
        my @conv = get_conv($xml);
        print_all_lines($window, $rows, @conv);
        $$window->refresh();
        sleep(5);
    }
}

1;

And the exact error message : Thread 1 terminated abnormally: Can't locate object method "query_form" via package "LWP::UserAgent" at get_xml.pm line 43.

Code that call the function :

#!/usr/bin/env perl

use strict;
use warnings;
use Curses;
use LWP::Simple;
use LWP::UserAgent;
use MIME::Base64;
use URI;
use threads;
use get_xml;
use post_xml;

# ... initialization of Curses windows ...
# $chat_win is a curse, $row is a number

my $server_endpoint = "...";
my $ua = LWP::UserAgent->new;
my $url = URI->new( "$server_endpoint/index.php" );
my $thread = threads->new(\&get_xml::write_conv_thread, \$chat_win, $row-4,"...", \$url, \$ua);
$thread->detach();

What can I do to make perl find the object method ?

Thank you for your answer.

nefas
  • 1,120
  • 7
  • 16
  • 3
    Well pretty simply, `query_form` isn't a method in `LWP::UserAgent`. It does exist in the `URI` module. Without seeing the code where you call `write_conv_thread`, it's not really possible to help you change that. – AKHolland Mar 23 '15 at 15:04
  • 1
    I'm confused by the `$$url`. If `$url` is an object, it should already be a scalar reference. In this case, it looks like you're code takes a reference of a reference. Is that correct? Unfortunately, there's not much here. I don't know how you constructed `$$url`, so I can't see what type of class it is. – David W. Mar 23 '15 at 15:10
  • I've edited my question to add the code that call write_conv_thread. $url is a reference. – nefas Mar 23 '15 at 15:30
  • 1
    We need the code where call query_form()... Approximately line 43 of get_xml.pm ... – Len Jaffe Mar 23 '15 at 15:47
  • 1
    Some off-topic comments about your code: 1) Your GUI library probably doesn't support being run in one thread and updated from another. You'll need to send the data to display to the display thread and have it update the windows. 2) You shouldn't be sharing objects between threads, and there's no need to share URL objects or UA objects here. Create them in your thread. 3) What's with the references? – ikegami Mar 23 '15 at 15:49
  • @Len Jaffe, He did provide *that*. Fourth line of `write_conv_thread`. – ikegami Mar 23 '15 at 15:49
  • I swear it wasn't there a minute ago :-) – Len Jaffe Mar 23 '15 at 16:22
  • @ikegami : 1)I just found that curse doesn't support to created in one thread and update in an other. The problem is that I need to update regularly. I'll try to notify the GUI to do the update with signal (when the thread that get the XML has retrieved the data, it will notify the GUI). Is it a viable option ? 2)OK, I will do that. – nefas Mar 23 '15 at 19:29
  • hum, is it possible to send a signal to a thread? Or maybe you mean signaling a condition variable (`cond_signal`). That's actually good. – ikegami Mar 23 '15 at 19:32
  • I was talking of send signal (I don't have found an other option :) ). From what I found it's possible. My problem is that on one side, I need to wait user input, on the other side, I need to check regularly (like every few seconde) result from a request and don't know how to do without signals (or updating window in an other thread but that's not possible). – nefas Mar 23 '15 at 19:40

1 Answers1

2

The (reference to the) UA got assigned to $url instead of $ua.

My best guess as to the cause (since you didn't provide the actual code that gives the error): $window, $rows or $username wasn't provided, causing the (reference to the) UA to be the fourth argument.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • If you can log fro your thread, dump the values of @_ and you should be able to see is something is missing from your invocation. – Len Jaffe Mar 23 '15 at 16:29
  • `warn("$_: ".( defined($_[$_]) ? "<<$_[$_]>>" : "[undef]" )) for 0..$#_;`, though probably easier just to look at the code. – ikegami Mar 23 '15 at 16:54
  • the error was due to a missing argument. @ikegami : your line of code makes me remember why it is said that perl is hard to read (and that I have a **lot** to learn :) ). – nefas Mar 23 '15 at 19:23