Re: forked process exiting before output read



On Fri, 27 Jul 2007 16:01:16 +0200
"Jeffrey Ratcliffe" <jeffrey ratcliffe gmail com> wrote:


Sometimes, updating the GUI takes longer than the child process, and
so the child process exits before the GUI has read all the data,
meaning that the last few images are missing. The following code
illustrates the point - the ProgressBar never reaches 100%.

Whilst I realise that I can write the info to a file, rather than the
socket (or pipe), or I could maintain a buffer, rather than reading
from the pipe a line at a time. Is there a Right Way to do this? Maybe
some way of signalling to the child process when the parent has
finished?
Regards
Jeff

If you use a thread, you can avoid this by placing the results in a shared variable.

Here is a simple threads example to give you the idea, it uses a reusable thread.
All you need to do, is store your thread's results in a shared var, and read it.

#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;
use Glib qw/TRUE FALSE/;
use Gtk2 qw/-init -threads-init/;

Glib::Object->set_threadsafe (TRUE);

#setup shared hash
my %shash;
share(%shash); #will work for first level keys

$shash{'go'} = 0;
$shash{'work'} = '';
$shash{'die'} = 0;

my $num:shared = 0;


my $window = Gtk2::Window->new('toplevel');
$window ->signal_connect( 'destroy' => \&delete_event );
$window->set_border_width(10);
$window->set_size_request(300,300);

my $vbox = Gtk2::VBox->new( FALSE, 6 );
$window->add($vbox);
$vbox->set_border_width(2);

my $hbox= Gtk2::HBox->new( FALSE, 6 );
my $hbox1 = Gtk2::HBox->new( FALSE, 6 );
$vbox->pack_end($hbox,FALSE,FALSE,0);
$vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0);
$vbox->pack_end($hbox1,FALSE,FALSE,0);
$hbox->set_border_width(2);
$vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0);

my $ebutton = Gtk2::Button->new_from_stock('gtk-quit');
$hbox->pack_end( $ebutton, FALSE, FALSE, 0 );
$ebutton->signal_connect( clicked => \&delete_event );

my $pbar = Gtk2::ProgressBar->new();
$pbar->set_pulse_step(.1);
$hbox->pack_start($pbar,1,1,0);


my $label_w_markup = Gtk2::Label->new();
$label_w_markup->set_markup("<span foreground=\"yellow1\" 
  size=\"40000\">$num</span>");

$vbox->pack_end($label_w_markup,FALSE,FALSE,4); 

######################################################

my $tbutton = Gtk2::Button->new_with_label('Run Thread');
 $hbox1->pack_start($tbutton , 1, 1, 0 );
my $lconnect = $tbutton->signal_connect( clicked => sub{ launch() });
my $sconnect;

$window->show_all();
$pbar->hide;   #needs to be called after show_all

#create 1 sleeping thread passing it the label and pbar to control
my $thread = threads->new(\&work, $label_w_markup, $pbar);

Gtk2->main;
######################################
sub delete_event {
  $shash{'go'} = 0;
  $shash{'die'} = 1;
  $thread->join;
  Gtk2->main_quit;
  return FALSE;
}
#######################################
sub launch{
   $pbar->show;
   $tbutton->set_label('Stop Thread');
   $tbutton->signal_handler_block($lconnect);
   $sconnect = $tbutton->signal_connect( clicked => sub{ stop() });
   $shash{'go'} = 1;
}
##################################################
sub stop{
   print "stopped\n";
   $shash{'go'} = 0;
   $pbar->hide;
   $tbutton->set_label('Run Thread');
   $tbutton->signal_handler_block ($sconnect);
   $tbutton->signal_handler_unblock ($lconnect);
}
#########################################################
sub work{
    
    my ($label,$pbar) = @_;
    $|++; 
    while(1){
       if($shash{'die'} == 1){ return }; 
      
       if ( $shash{'go'} == 1 ){
        
         $num = 0;
         while(1){
                $num++;
                
                if($num > 30){last}
                     
                 Glib::Idle->add(
                   sub{
                    if($shash{'die'} == 1){ return };
                    $label->set_markup("<span foreground=\"yellow1\" 
                    size=\"40000\">$num</span>");
                    $pbar->pulse;
                    return FALSE;
                   });
                
                select(undef,undef,undef, .1);

            if($shash{'go'} == 0){last}
            if($shash{'die'} == 1){ return }; 
           }
       
       #if reach this point, the thread has finished
          print "my results = $num\n";   

         Glib::Idle->add(
                   sub{
                    if($shash{'die'} == 1){ return };
                    $label->set_markup("<span foreground=\"green\" 
                    size=\"60000\">$num</span>");
                    $pbar->hide;
                    return FALSE;
                   });
       
           $shash{'go'} = 0; #turn off self before returning      
       }else
         { select(undef,undef,undef,.1) } #sleep time
    }
}
##############################################



__END__

-- 
I'm not really a human, but I play one on earth.
http://zentara.net/japh.html



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]