deadpickle has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to get threads to work. When I run the program I get the error: Use of uninitialized value in numeric eq (==) at tray.pl line 256. Use of uninitialized value in numeric eq (==) at tray.pl line 257. These errors are located in the subroutine &sftp and are the first two shared variables.

Also, the $thread_1->join; will not exit the thread when quit is clicked.

#!/usr/bin/perl -w use strict; use warnings; use threads; use threads::shared; use Glib qw/TRUE FALSE/; #threads my $thread_1 = threads->new( \&sftp); use Gtk2 '-init'; use Gtk2::TrayIcon; #user variables my $icon_file = Gtk2::Gdk::Pixbuf->new_from_file("/home/deadpickle/Des +ktop/Gtk2/test.png"); my $time = 1200000; #global variables my $user : shared = 'uas'; my $server : shared = 'updraft.unl.edu'; my $local_waypoint : shared = '/local'; my $remote_waypoint : shared = '/remote'; my $waytemp : shared = 'waytemp'; my $wayfinal : shared = 'wayfinal'; my $file = 'default.cfg'; my $local_uaspos : shared = '/local'; my $remote_uaspos : shared = '/remote'; my $local_uas : shared = '/local'; my $remote_uas : shared = '/remote'; my $die : shared = 0; my $sftp_connect : shared = 0; #icon goes in box, box goes in tray my $icon = Gtk2::Image->new_from_pixbuf($icon_file); my $eventbox = Gtk2::EventBox->new; $eventbox->add($icon); my $tray = Gtk2::TrayIcon->new('Test'); $tray->add($eventbox); #tooltip my $tooltip = Gtk2::Tooltips->new; $tooltip->set_tip($tray, "GRRUVI v1.0"); #events and timeouts $eventbox->signal_connect('button_release_event', \&click); #show tray $tray->show_all; #end event loop Gtk2->main; #handles tray clicks sub click { #left mouse button if ($_[1]->button == 1) { #what should this do? #&open_woot(); } #right mouse button elsif ($_[1]->button == 3) { &menu(); } return 1; } #right click menu sub menu { my $menu = Gtk2::Menu->new(); #UVNav my $menu_UVNav = Gtk2::ImageMenuItem->new_with_label("UVNav"); $menu_UVNav->signal_connect(activate => \&UVNav); $menu_UVNav->set_image(Gtk2::Image->new_from_stock('gtk-refresh', +'menu')); $menu->add($menu_UVNav); #VCI my $menu_VCI = Gtk2::ImageMenuItem->new_with_label("VCI"); $menu_VCI->signal_connect(activate => \&VCI); $menu_VCI->set_image(Gtk2::Image->new_from_stock('gtk-refresh', 'm +enu')); $menu->add($menu_VCI); #configure my $menu_pref = Gtk2::ImageMenuItem->new_with_label("Configure"); $menu_pref->signal_connect(activate => \&configure); $menu_pref->set_image(Gtk2::Image->new_from_stock('gtk-preferences +', 'menu')); $menu->add($menu_pref); #separator my $menu_sep = Gtk2::SeparatorMenuItem->new(); $menu->add($menu_sep); #Quit my $menu_quit = Gtk2::ImageMenuItem->new_with_label("Quit"); $menu_quit->signal_connect(activate => sub { $die = 1; $thread_1-> +join; Gtk2->main_quit;} ); $menu_quit->set_image(Gtk2::Image->new_from_stock('gtk-quit', 'men +u')); $menu->add($menu_quit); $menu->show_all; #popup menu, the three is for right mouse button $menu->popup(undef,undef,undef,3,undef,undef); return 1; } #UVNav interface sub UVNav { } #VCI displays sub VCI { } #configuration dialog window sub configure { #Create the new window my $config_window = Gtk2::Window->new('toplevel'); $config_window->set_title("Configuration"); $config_window->set_position('center'); #VBox container my $table_config = Gtk2::Table->new(3, 5, FALSE); #Create Notebook my $config_notebook = Gtk2::Notebook->new; $config_notebook->set_tab_pos('top'); #the First Page; Config file select my $hbox_file = Gtk2::HBox->new(FALSE, 1); my $label_file = Gtk2::Label->new('Configuration Filename'); my $entry_file = Gtk2::Entry->new; my $button_file = Gtk2::Button->new_with_mnemonic("_Browse"); $button_file->set_size_request( 80, 32); my $align_button_file = Gtk2::Alignment->new( 0.5, 0.5, 0, 0); $align_button_file->add( $button_file); $entry_file->set_text($file); $hbox_file->pack_start($label_file, FALSE, FALSE, 1); $hbox_file->pack_start($entry_file, FALSE, FALSE, 1); $hbox_file->pack_start($align_button_file, FALSE, FALSE, 1); #the Second Page; Connection my $connect_vbox = Gtk2::VBox->new( FALSE, 1); my $label_user = Gtk2::Label->new('Username'); my $entry_user = Gtk2::Entry->new; my $label_server = Gtk2::Label->new('Server'); my $entry_server = Gtk2::Entry->new; $entry_user->set_text($user); $entry_server->set_text($server); $connect_vbox->pack_start($label_user, FALSE, FALSE, 1); $connect_vbox->pack_start($entry_user, FALSE, FALSE, 1); $connect_vbox->pack_start($label_server, FALSE, FALSE, 1); $connect_vbox->pack_start($entry_server, FALSE, FALSE, 1); #the Third Page; Waypoint my $table_waypoint = Gtk2::Table->new(4, 2, FALSE); my $label_temp_waypoint = Gtk2::Label->new('Temp Waypoint Filename +'); my $entry_temp_waypoint = Gtk2::Entry->new; my $label_final_waypoint = Gtk2::Label->new('Final Waypoint Filena +me'); my $entry_final_waypoint = Gtk2::Entry->new; my $label_local_waypoint = Gtk2::Label->new('Local Waypoint Folder +'); my $entry_local_waypoint = Gtk2::Entry->new; my $label_remote_waypoint = Gtk2::Label->new('Remote Waypoint Fold +er'); my $entry_remote_waypoint = Gtk2::Entry->new; $entry_temp_waypoint->set_text($waytemp); $entry_final_waypoint->set_text($wayfinal); $entry_local_waypoint->set_text($local_waypoint); $entry_remote_waypoint->set_text($remote_waypoint); $entry_temp_waypoint->set_editable(0); $entry_final_waypoint->set_editable(0); $table_waypoint->attach_defaults($label_temp_waypoint, 0, 1, 0, 1) +; $table_waypoint->attach_defaults($entry_temp_waypoint, 1, 2, 0, 1) +; $table_waypoint->attach_defaults($label_final_waypoint, 0, 1, 1, 2 +); $table_waypoint->attach_defaults($entry_final_waypoint, 1, 2, 1, 2 +); $table_waypoint->attach_defaults($label_local_waypoint, 0, 1, 2, 3 +); $table_waypoint->attach_defaults($entry_local_waypoint, 1, 2, 2, 3 +); $table_waypoint->attach_defaults($label_remote_waypoint, 0, 1, 3, +4); $table_waypoint->attach_defaults($entry_remote_waypoint, 1, 2, 3, +4); #the Fourth Page; UAS my $vbox_uas = Gtk2::VBox->new( FALSE, 1); my $table_uaspos = Gtk2::Table->new(4, 2, FALSE); my $frame_uaspos = Gtk2::Frame->new( 'uasposition File Transfer'); my $label_local_uaspos = Gtk2::Label->new('Local uasposition Folde +r'); my $entry_local_uaspos = Gtk2::Entry->new; my $label_remote_uaspos = Gtk2::Label->new('Remote uasposition Fol +der'); my $entry_remote_uaspos = Gtk2::Entry->new; $entry_local_uaspos->set_text($local_uaspos); $entry_remote_uaspos->set_text($remote_uaspos); $table_uaspos->attach_defaults($label_local_uaspos, 0, 1, 0, 1); $table_uaspos->attach_defaults($entry_local_uaspos, 1, 2, 0, 1); $table_uaspos->attach_defaults($label_remote_uaspos, 0, 1, 1, 2); $table_uaspos->attach_defaults($entry_remote_uaspos, 1, 2, 1, 2); $frame_uaspos->add( $table_uaspos); my $table_uas = Gtk2::Table->new(4, 2, FALSE); my $frame_uas = Gtk2::Frame->new( 'UAS Placefile Transfer'); my $label_local_uas = Gtk2::Label->new('Local uaspf.txt Folder'); my $entry_local_uas = Gtk2::Entry->new; my $label_remote_uas = Gtk2::Label->new('Remote uaspf.txt Folder') +; my $entry_remote_uas = Gtk2::Entry->new; $entry_local_uas->set_text($local_uas); $entry_remote_uas->set_text($remote_uas); $table_uas->attach_defaults($label_local_uas, 0, 1, 0, 1); $table_uas->attach_defaults($entry_local_uas, 1, 2, 0, 1); $table_uas->attach_defaults($label_remote_uas, 0, 1, 1, 2); $table_uas->attach_defaults($entry_remote_uas, 1, 2, 1, 2); $frame_uas->add( $table_uas); $vbox_uas->pack_start($frame_uaspos, FALSE, FALSE, 1); $vbox_uas->pack_start($frame_uas, FALSE, FALSE, 1); #append pages $config_notebook->append_page($hbox_file, "Configuration File"); $config_notebook->append_page($connect_vbox, "Connection"); $config_notebook->append_page($table_waypoint, "Waypoint"); $config_notebook->append_page($vbox_uas, "UAS Settings"); #add button to the main window my $button_accept = Gtk2::Button->new_with_mnemonic("_Accept"); my $button_cancel = Gtk2::Button->new_with_mnemonic("_Cancel"); #pack them into the dialog window $table_config->attach_defaults($config_notebook, 0, 5, 0, 1); $table_config->attach_defaults($button_accept, 1, 2, 2, 3); $table_config->attach_defaults($button_cancel, 3, 4, 2, 3); $config_window->add($table_config); $config_window->show_all; #Button Functions $button_cancel->signal_connect('clicked' => sub {$config_window->d +estroy}); $button_accept->signal_connect('clicked' => sub { my @settings = ( + ($user = $entry_user->get_text), ($server = $entry_server->get_text) + ,($local_waypoint = $entry_local_waypoint->get_text), ($remote_waypo +int = $entry_remote_waypoint->get_text), ($local_uaspos = $entry_loca +l_uaspos->get_text), ($remote_uaspos = $entry_remote_uaspos->get_text +), ($local_uas = $entry_local_uas->get_text), ($remote_uas = $entry_r +emote_uas->get_text)); save_default(@settings); $config_window->destr +oy}); $button_file->signal_connect('clicked' => sub {my $chooser_file = +Gtk2::FileChooserDialog->new ( 'Open Config File...', undef, 'open')} +); } #save to the file default.cfg when apply is clicked sub save_default { open DEFAULT, '>', 'default.cfg' or die "Could not Open file!! $!" +; for (@_) { print DEFAULT "$_\n"; } close DEFAULT; } #thread 1; SFTP connection thread sub sftp{ $|++; while(1){ if ( $die == 1 ){ goto END }; if ( $sftp_connect == 1 ){ my $seconds = 120; my %args = (host=> $server, user=>$user, timeout=>$seconds +); my $sftp = Net::SFTP::Foreign->new(%args); for(;;){ if($sftp_connect == 0){ $sftp_connect = 0; last} if($die == 1){ goto END }; } undef $sftp; # $go = 0; }else { sleep 1 } } END: }

Replies are listed 'Best First'.
Re: Gtk2 and Threads
by Anonymous Monk on Jul 21, 2007 at 06:34 UTC
    #!/usr/bin/perl # # $Header: /cvsroot/gtk2-perl/gtk2-perl-xs/Gtk2/examples/thread_usage. +pl,v 1.4 2004/06/23 01:00:15 rwmcfa1 Exp $ # # -rm # use strict; use warnings; use Data::Dumper; use Glib qw(TRUE FALSE); use Gtk2 qw/-init -threads-init 1.050/; die "Glib::Object thread safetly failed" unless Glib::Object->set_threadsafe (TRUE); my $win = Gtk2::Window->new; $win->signal_connect (destroy => sub { Gtk2->main_quit; }); $win->set_title ($0); $win->set_border_width (6); $win->set_default_size (640, 480); my $hbox = Gtk2::HBox->new (FALSE, 6); $win->add ($hbox); my $vbox = Gtk2::VBox->new (FALSE, 6); $hbox->pack_start ($vbox, FALSE, FALSE, 0); my $worklog = Log->new; $hbox->pack_start ($worklog, TRUE, TRUE, 0); my @workers; my $worker; foreach (1..5) { $worker = Worker->new ($worklog); $vbox->pack_start ($worker, FALSE, FALSE, 0); $worker->set_worker_label ('Worker '.$_); push @workers, $worker; } my $pending = Gtk2::Label->new ('0 jobs pending'); $vbox->pack_start ($pending, FALSE, FALSE, 0); Glib::Timeout->add (500, sub { $pending->set_text (Worker->jobs_pending.' jobs pending'); 1; }); my $count = 0; my $go = Gtk2::Button->new ('_Go'); $vbox->pack_start ($go, FALSE, FALSE, 0); $go->signal_connect (clicked => sub { foreach (@workers) { Worker->do_job ($count + rand); $count++; } }); my $quit = Gtk2::Button->new_from_stock ('gtk-quit'); $vbox->pack_start ($quit, FALSE, FALSE, 0); $quit->signal_connect (clicked => sub { $go->set_sensitive (FALSE); $quit->set_sensitive (FALSE); Worker->all_fired; Gtk2->main_quit; }); $win->show_all; Gtk2->main; package Worker; use strict; use warnings; use Data::Dumper; use threads; use threads::shared; use Thread::Queue; use Glib qw(TRUE FALSE); use base 'Gtk2::HBox'; our $_nworkers : shared = 0; my $_jobs; BEGIN { $_jobs = Thread::Queue->new; } sub do_job { shift; # class $_jobs->enqueue (shift); } sub all_fired { shift; # class # put on a quit command for each worker foreach (1..$_nworkers) { $_jobs->enqueue (undef); } while ($_nworkers) { Gtk2->main_iteration; } } sub jobs_pending { return $_jobs->pending; } sub new { my $class = shift; my $worklog = shift; my $self = Gtk2::HBox->new (FALSE, 6); # rebless to a worker bless $self, $class; # gui section my $label = Gtk2::Label->new ('Worker:'); $self->pack_start ($label, FALSE, FALSE, 0); my $progress = Gtk2::ProgressBar->new; $self->pack_start ($progress, FALSE, FALSE, 0); $progress->set_text ('Idle'); $self->{label} = $label; $self->{progress} = $progress; $self->{worklog} = $worklog; # thread section $self->{child} = threads->new (\&_worker_thread, $self); $_nworkers++; return $self; } sub set_worker_label { my $self = shift; my $name = shift; $self->{label}->set_text ($name); } sub _worker_thread { my $self = shift; my $progress = $self->{progress}; my $worklog = $self->{worklog}; my $i; my $job; my $sleep; # undef job means quit while (defined ($job = $_jobs->dequeue)) { $worklog->insert_msg ($self->{label}->get_text ." is doing job ($job)\n"); if (rand > 0.5) { $sleep = 1 + rand; } else { $sleep = 1 - rand; } for ($i = 0; $i < 1.1; $i += 0.25) { Gtk2::Gdk::Threads->enter; $progress->set_fraction ($i); $progress->set_text ($i * 100 .'%'); Gtk2::Gdk::Threads->leave; # we're state employee's, so let's do some 'work'... sleep $sleep; } $worklog->insert_msg ($self->{label}->get_text ." done with job ($job)\n"); } $_nworkers--; } package Log; use strict; use warnings; use Glib qw(TRUE FALSE); use base 'Gtk2::ScrolledWindow'; sub new { my $class = shift; my $self = Gtk2::ScrolledWindow->new; my $buffer = Gtk2::TextBuffer->new; my $view = Gtk2::TextView->new_with_buffer ($buffer); $self->add ($view); $view->set (editable => FALSE, cursor_visible => FALSE); $self->{view} = $view; $self->{buffer} = $buffer; bless $self, $class; $self->insert_msg ("Start...\n------------------------------------ +-\n"); return $self; } sub insert_msg { my $self = shift; my $msg = shift; my $buffer = $self->{buffer}; Gtk2::Gdk::Threads->enter; my $iter = $buffer->get_end_iter; $buffer->insert ($iter, $msg); $iter = $buffer->get_end_iter; $self->{view}->scroll_to_iter ($iter, 0.0, FALSE, 0.0, 0.0); Gtk2::Gdk::Threads->leave; }
Re: Gtk2 and Threads
by zentara (Cardinal) on Jul 21, 2007 at 11:58 UTC
    You need to learn more about threads in general...... shared variables need to be declared BEFORE the thread is created. This should get you going in the right direction.
    #!/usr/bin/perl -w use strict; use warnings; use threads; use threads::shared; use Glib qw/TRUE FALSE/; my $user : shared = 'uas'; my $server : shared = 'updraft.unl.edu'; my $local_waypoint : shared = '/local'; my $remote_waypoint : shared = '/remote'; my $waytemp : shared = 'waytemp'; my $wayfinal : shared = 'wayfinal'; my $local_uaspos : shared = '/local'; my $remote_uaspos : shared = '/remote'; my $local_uas : shared = '/local'; my $remote_uas : shared = '/remote'; my $die : shared = 0; my $sftp_connect : shared = 0; #threads my $thread_1 = threads->new( \&sftp);

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum