Signals & MacOS

2015-02-12 Thread Jeffrey Ratcliffe
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

2015-03-13 Thread Jeffrey Ratcliffe
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

2015-02-12 Thread Brian Manning
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

2015-03-31 Thread Jeffrey Ratcliffe
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

2015-03-31 Thread Brian Manning
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

2015-04-01 Thread Jeffrey Ratcliffe
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

2015-04-01 Thread Brian Manning
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

2015-04-07 Thread Jeffrey Ratcliffe
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