Signals & MacOS
I've got code with Glib::IO->add_watch() to watch for in or hup signals in a pipe that has always worked fine on Linux. A colleague of mine tried it on his MacOS box - and the hup is never caught. Indeed, in seem to be thrown a great deal, even when there is nothing to read. Is there a known list of issues that have to be handled differently under MacOS? I've no access to MacOS, so debugging is hard. Regards Jeff ___ gtk-perl-list mailing list gtk-perl-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-perl-list
Signals & MacOS
Now, at last with a small working example. The following code works fine on Linux, but on MacOS: a. the gui does not seem to respond to the "hup" signal from the subprocess b. gets far more "in" signals than it should Unfortunately, the above description is secondhand, as I do not have access to a Mac. I would be very glad if somebody could give me a clue how to get things working under both operating systems. Regards Jeff #!/usr/bin/perl use warnings; use strict; use Gtk2 -init; use Glib qw(TRUE FALSE);# To get TRUE and FALSE use POSIX qw(locale_h :signal_h :errno_h :sys_wait_h); use IPC::Open3; use IO::Handle; use Readonly; Readonly my $_POLL_INTERVAL => 100;# ms Readonly my $_1KB => 1024; my $EMPTY = q{}; # Create the windows my $window = Gtk2::Window->new('toplevel'); my $box = Gtk2::VBox->new; my $entry = Gtk2::Entry->new; my $pbar= Gtk2::ProgressBar->new; my $qbutton = Gtk2::Button->new('Quit'); my $sbutton = Gtk2::Button->new('Start'); $window->add($box); $box->add($pbar); $box->add($qbutton); $box->add($sbutton); # We should also link this to the destroy message on the main window, # this is just quick and dirty $qbutton->signal_connect( clicked => sub { Gtk2->main_quit } ); $sbutton->signal_connect( clicked => \&start_process ); $window->show_all; Gtk2->main; sub start_process { watch_cmd( cmd => 'for i in `seq 1 5`; do echo $i; sleep 1; done', running_callback => sub { $pbar->pulse; }, started_callback => sub { $pbar->set_text('Started'); }, out_callback => sub { my ($line) = @_; $pbar->set_text($line); }, err_callback => sub { my ($line) = @_; $pbar->set_text("Error: $line"); }, finished_callback => sub { $pbar->set_text('Finished'); }, ); return; } sub watch_cmd { my (%options) = @_; my $out_finished = FALSE; my $err_finished = FALSE; my $error_flag = FALSE; print "$options{cmd}\n"; if ( defined $options{running_callback} ) { my $timer = Glib::Timeout->add( $_POLL_INTERVAL, sub { $options{running_callback}->(); return Glib::SOURCE_REMOVE if ( $out_finished or $err_finished ); return Glib::SOURCE_CONTINUE; } ); } my ( $write, $read ); my $error = IO::Handle->new; my $pid = IPC::Open3::open3( $write, $read, $error, $options{cmd} ); print "Forked PID $pid\n"; if ( defined $options{started_callback} ) { $options{started_callback}->() } my ( $stdout, $stderr, $error_message ); add_watch( $read, sub { my ($line) = @_; $stdout .= $line; if ( defined $options{out_callback} ) { $options{out_callback}->($line); } }, sub { # Don't flag this until after the callback to avoid the race condition # where stdout is truncated by stderr prematurely reaping the process $out_finished = TRUE; }, sub { ($error_message) = @_; $error_flag = TRUE; } ); add_watch( $error, sub { my ($line) = @_; $stderr .= $line; if ( defined $options{err_callback} ) { $options{err_callback}->($line); } }, sub { # Don't flag this until after the callback to avoid the race condition # where stderr is truncated by stdout prematurely reaping the process $err_finished = TRUE; }, sub { ($error_message) = @_; $error_flag = TRUE; } ); # Watch for the process to hang up before running the finished callback Glib::Child->watch_add( $pid, sub { # Although the process has hung up, we may still have output to read, # so wait until the _watch_add flags that the process has ended first. my $timer = Glib::Timeout->add( $_POLL_INTERVAL, sub { if ($error_flag) { if ( defined $options{error_callback} ) { $options{error_callback}->($error_message); } return Glib::SOURCE_REMOVE; } elsif ( $out_finished and $err_finished ) { if ( defined $options{finished_callback} ) { $options{finished_callback}->( $stdout, $stderr ); } print "Waiting to reap process\n"; # -1 indicates a non-blocking wait for all pending zombie processes print 'Reaped PID ', waitpid( -1,## no critic (Prohibit
Re: Signals & MacOS
On Thu, Feb 12, 2015 at 1:48 PM, Jeffrey Ratcliffe wrote: > I've got code with Glib::IO->add_watch() to watch for in or hup > signals in a pipe that has always worked fine on Linux. A colleague of > mine tried it on his MacOS box - and the hup is never caught. > > Indeed, in seem to be thrown a great deal, even when there is nothing to read. > > Is there a known list of issues that have to be handled differently under > MacOS? Do you have a short sample that demonstrates the problem? Thanks, Brian ___ gtk-perl-list mailing list gtk-perl-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Signals & MacOS
Does nobody have a Mac? Or at least a little insight? Regards Jeff On 13 March 2015 at 22:41, Jeffrey Ratcliffe wrote: > Now, at last with a small working example. The following code works > fine on Linux, but on MacOS: > > a. the gui does not seem to respond to the "hup" signal from the subprocess > b. gets far more "in" signals than it should > > Unfortunately, the above description is secondhand, as I do not have > access to a Mac. > > I would be very glad if somebody could give me a clue how to get > things working under both operating systems. > > Regards > > Jeff > > #!/usr/bin/perl > > use warnings; > use strict; > use Gtk2 -init; > use Glib qw(TRUE FALSE);# To get TRUE and FALSE > use POSIX qw(locale_h :signal_h :errno_h :sys_wait_h); > use IPC::Open3; > use IO::Handle; > use Readonly; > Readonly my $_POLL_INTERVAL => 100;# ms > Readonly my $_1KB => 1024; > my $EMPTY = q{}; > > # Create the windows > my $window = Gtk2::Window->new('toplevel'); > my $box = Gtk2::VBox->new; > my $entry = Gtk2::Entry->new; > my $pbar= Gtk2::ProgressBar->new; > my $qbutton = Gtk2::Button->new('Quit'); > my $sbutton = Gtk2::Button->new('Start'); > > $window->add($box); > $box->add($pbar); > $box->add($qbutton); > $box->add($sbutton); > > # We should also link this to the destroy message on the main window, > # this is just quick and dirty > $qbutton->signal_connect( clicked => sub { Gtk2->main_quit } ); > $sbutton->signal_connect( clicked => \&start_process ); > $window->show_all; > Gtk2->main; > > sub start_process { > watch_cmd( > cmd => 'for i in `seq 1 5`; do echo $i; sleep 1; done', > running_callback => sub { > $pbar->pulse; > }, > started_callback => sub { > $pbar->set_text('Started'); > }, > out_callback => sub { > my ($line) = @_; > $pbar->set_text($line); > }, > err_callback => sub { > my ($line) = @_; > $pbar->set_text("Error: $line"); > }, > finished_callback => sub { > $pbar->set_text('Finished'); > }, > ); > return; > } > > sub watch_cmd { > my (%options) = @_; > > my $out_finished = FALSE; > my $err_finished = FALSE; > my $error_flag = FALSE; > print "$options{cmd}\n"; > > if ( defined $options{running_callback} ) { > my $timer = Glib::Timeout->add( > $_POLL_INTERVAL, > sub { > $options{running_callback}->(); > return Glib::SOURCE_REMOVE > if ( $out_finished or $err_finished ); > return Glib::SOURCE_CONTINUE; > } > ); > } > > my ( $write, $read ); > my $error = IO::Handle->new; > my $pid = IPC::Open3::open3( $write, $read, $error, $options{cmd} ); > print "Forked PID $pid\n"; > > if ( defined $options{started_callback} ) { > $options{started_callback}->() } > my ( $stdout, $stderr, $error_message ); > > add_watch( > $read, > sub { > my ($line) = @_; > $stdout .= $line; > if ( defined $options{out_callback} ) { > $options{out_callback}->($line); > } > }, > sub { > > # Don't flag this until after the callback to avoid the race > condition > # where stdout is truncated by stderr prematurely reaping the > process > $out_finished = TRUE; > }, > sub { > ($error_message) = @_; > $error_flag = TRUE; > } > ); > add_watch( > $error, > sub { > my ($line) = @_; > $stderr .= $line; > if ( defined $options{err_callback} ) { > $options{err_callback}->($line); > } > }, > sub { > > # Don't flag this until after the callback to avoid the race > condition > # where stderr is truncated by stdout prematurely reaping the > process > $err_finished = TRUE; > }, > sub { > ($error_message) = @_; > $error_flag = TRUE; > } > ); > > # Watch for the process to hang up before running the finished callback > Glib::Child->watch_add( > $pid, > sub { > > # Although the process has hung up, we may still have output to > read, > # so wait until the _watch_add flags that the process has ended > first. > my $timer = Glib::Timeout->add( > $_POLL_INTERVAL, > sub { > if ($error_flag) { > if ( defined $options{error_callback} ) { > $options{error_callback}->($error_message); > } > return Glib::SOURCE_REMOVE; > } > elsif ( $out_finished and $e
Re: Signals & MacOS
On Tue, Mar 31, 2015 at 1:07 PM, Jeffrey Ratcliffe wrote: > Does nobody have a Mac? Or at least a little insight? Macs I have, but spare time right now... not so much. One suggestion would be to replace the Glib::IO->add_watch with a normal Perl signal handler (via %SIG), or another Perl module that can handle signals, and see if you still run into same problem. I also found these after a quick Google search: http://perldoc.perl.org/sigtrap.html http://perltricks.com/article/37/2013/8/18/Catch-and-Handle-Signals-in-Perl http://search.cpan.org/~mob/Signals-XSIG-0.13/lib/Signals/XSIG.pm http://blog.booking.com/devel-tracksig-the-signal-handling-blues.html The last link mentions Devel::TrackSIG for debugging signal handling in Perl. Thanks, Brian ___ gtk-perl-list mailing list gtk-perl-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Signals & MacOS
On 31 March 2015 at 22:56, Brian Manning wrote: > Macs I have, but spare time right now... not so much. I know the problem. > One suggestion would be to replace the Glib::IO->add_watch with a > normal Perl signal handler (via %SIG), or another Perl module that can > handle signals, and see if you still run into same problem. Thanks for the help. Maybe I'm being dull, but I don't see how to do that. Glib::IO->add_watch() looks for events (GIO::Conditions) on a file descriptor, not signals in the normal sense. Or am I missing something? Regards Jeff ___ gtk-perl-list mailing list gtk-perl-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Signals & MacOS
On Wed, Apr 1, 2015 at 1:47 PM, Jeffrey Ratcliffe wrote: > Maybe I'm being dull, but I don't see how to do that. > Glib::IO->add_watch() looks for events (GIO::Conditions) on a file > descriptor, not signals in the normal sense. Or am I missing > something? Nope, my bad. Maybe select/IO::Select on your file descriptors then, to see if you get the same behavior? Thanks, Brian ___ gtk-perl-list mailing list gtk-perl-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-perl-list
Re: Signals & MacOS
On 2 April 2015 at 01:17, Brian Manning wrote: > Maybe select/IO::Select on your file descriptors then, to see if you > get the same behavior? Thanks for the tip, but my reading of select/IO::Select is that they always block, whereas the nice thing about Glib::IO->add_watch() is that it sets up a callback. To use a blocking watch in a GUI, I would have to put it in a thread, and presumably the only way of then killing the blocking watch would be to kill the thread. Is no one using Glib::IO->add_watch() on a Mac? Regards Jeff ___ gtk-perl-list mailing list gtk-perl-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-perl-list