in reply to Re: Perl/Tk Multithreading
in thread Perl/Tk Multithreading

Thank you for your kind suggestions. All your guess is truly my problem.

1. I tried to confine ALL code of GSM module to the thread

2. I am getting the following error:

"Thread 1 terminated abnormally: Can't call method "purge_all" on an undefined value at widget.pl line 4198."

3. The subroutine in which the "purge_all" appears is given below:

(Note: this method is take from Module Device::Modem so i did not code this subroutine. Only thing I am passing arguments to this subroutine from my program).For complete code this module please see CPAN

sub atsend { my ( $me, $msg ) = @_; my $cnt = 0; print "\nThe port \$me in keypress function is $me\n"; # Write message on port $me->port->purge_all; $cnt = $me->port->write($msg); my $lbuf=length($msg); my $ret; while ($cnt < $lbuf) { $ret = $me->port->write(substr($msg, $cnt)); $me->write_drain(); last unless defined $ret; $cnt += $ret; } $me->log->write('debug', 'atsend: wrote '.$cnt.'/'.length($msg).' +chars'); # If wrote all chars of `msg', we are successful return $cnt == length $msg; }

4. In the above subroutine the error is exactly coming at the line:  $me->port->purge_all;

5. The subroutine which calls the above module subroutine from my program is given below:

sub keypress { my ($port_no,$key) = @_; $port_no =~ m/(\d+)/g; print "\nThe port \$port_no in keypress function is $port_no\n"; my $ms=$1; use Device::Modem::GSM; my $mod= new Device::Modem::GSM(port => "/dev/$port_no", log=> 'file,logfile.log', loglevel => 'info' # default is 'war +ning' ); $modem[$ms]=$mod; $key =~ s/^\s+//;# to remove leading whitespace $key =~ s/\s+$//;# to remove trailing whitespace my $st = "AT+CKPD="."\"$key\"".",1,1" ; $modem[$ms]-> atsend($st . Device::Modem::CR); my ($ok, $response) = $modem[$ms]->parse_answer($Device::Modem::STD_RE +SPONSE); return "$ok"; }

6.Additional Information:

a)The value of arguments passed to the module subroutine atsend() from my program subroutine keypress()are:

AT+CKPD="m",1,1

b)The value of the arguments received in the atsend() subroutine for variable $me is:

Device::Modem::GSM=HASH(0xaece500)

Note: This values I got from compiling.

So whats the problem here? why it is not able to call method in Modem.pm module?

My program owrks like gem when same arguments are passed without creating a thread.

Replies are listed 'Best First'.
Re^3: Perl/Tk Multithreading
by zentara (Cardinal) on Jul 19, 2011 at 12:31 UTC
    So whats the problem here? why it is not able to call method in Modem.pm module? My program works like gem when same arguments are passed without creating a thread.

    I tried to follow your description of the problem, but it still isn't clear that you are confining all of your network code to the worker thread as you seem to be creating the Device::Modem::GSM object in your keypress subroutine, which I assume is in your main thread.

    The problem does seem familiar to me though, as I had to work thru similar issues with various threaded programs. The general safe rule is only communicate with the thread thru shared variables, or options passed to the thread during thread->create. That means if you receive a keypress in your main thread, transfer it to a shared variable designed to hold it, then somehow get the thread to read the information from the shared variable, and do what needs to be done.

    So your use Device::Modem::GSM; statement, as well as my $mod= new Device::Modem::GSM() statement, should be confined to the thread, and your keypresses should be passed in thru a shared variable.

    If you havn't figured it out yet, by seeing it mentioned in numerous posts in the archives, but Perl threads are created by a copy-on-create method, which makes an exact copy of the parent thread at the time of creation. So, when you create a Device::Modem::GSM object in the main thread, after the worker thread gets created, the worker thread has to use try and access the object in the main thread, crossing a safety barrier, and it is the source of all sorts of errors like you are getting. Or, if you create the Device::Modem::GSM() object before the thread is created, there are essentially 2 objects, 1 in main, and a copy in the thread... that causes boundary errors too.

    I know you probably have invested quite a bit of time into your Tk frontend to this, but you may want to switch to Gtk2, because it has improved thread safety features, and can use subs which are common amoung threads, thru it's Glib::Idle->add method.

    But if you stick with Tk, make sure ALL network code is confined to the worker thread, and only communicate with the thread thru pre-defined shared variables. That means in your worker thread, you will need a loop of some sort to pick up the keypresses which your main thread has put in a shared variable. Don't try to pass the sub created in main, with options to the thread.


    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh

      " So, when you create a Device::Modem::GSM object in the main thread, after the worker thread gets created, the worker thread has to use try and access the object in the main thread, crossing a safety barrier, and it is the source of all sorts of errors like you are getting. Or, if you create the Device::Modem::GSM() object before the thread is created, there are essentially 2 objects, 1 in main, and a copy in the thread... that causes boundary errors too."

      .............................................................

      Thank you for your valuable suggestions. I am able to solve the problem.

      ............................................................

      But as per requirements of my GUI it looks a partial solution!!!