in reply to Please suggest a non-forking way to do this (OS: windows)
use strict; use warnings; use Win32::API qw( ); use Win32API::File qw( GetOsFHandle INVALID_HANDLE_VALUE ); use Tk qw( MainLoop ); use constant ERROR_BROKEN_PIPE => 109; BEGIN { # BOOL WINAPI PeekNamedPipe( # __in HANDLE hNamedPipe, # __out_opt LPVOID lpBuffer, # __in DWORD nBufferSize, # __out_opt LPDWORD lpBytesRead, # __out_opt LPDWORD lpTotalBytesAvail, # __out_opt LPDWORD lpBytesLeftThisMessage # ) my $f = Win32::API->new('kernel32', 'PeekNamedPipe', 'LPLPPP', 'L') or die $^E; sub PeekNamedPipe { my $vBuffer = defined($_[1]) ? $vBuffer : 0; my $nBytesRead = defined($_[3]) ? pack('L!', $_[3]) : 0; my $nTotalBytesAvail = defined($_[4]) ? pack('L!', $_[4]) : 0; my $nBytesLeftThisMsg = defined($_[5]) ? pack('L!', $_[5]) : 0; my $rv = $f->Call( $_[0], $vBuffer, $_[2], $nBytesRead, $nTotalBytesAvail, $nBytesLeftThisMsg, ); $_[1] = $vBuffer if defined $_[1]; $_[3] = unpack('L!', $nBytesRead ) if defined $_[3]; $_[4] = unpack('L!', $nTotalBytesAvail ) if defined $_[4]; $_[5] = unpack('L!', $nBytesLeftThisMsg) if defined $_[5]; return $rv; } } my $mw; my $text; my $startb; my $repeater; my $count; BEGIN { $count = ''; } my $pid; my $fh_pipe; my $fd_pipe; sub start { $startb->configure( -state => 'disabled' ); return if defined($pid); my $cmd = qq{"$^X"} . q{ -le"$|++;print(''.localtime),sleep(1) for 1..10"}; $pid = open($fh_pipe, "$cmd 2>&1 |") or die $!; ( $fd_pipe = GetOsFHandle( $fh_pipe ) ) != INVALID_HANDLE_VALUE or die $^E; $count = 0; $repeater = $mw->repeat(10, \&poll); } sub stop { my ($force) = @_; undef $repeater; $count = ''; kill TERM => $pid if $pid; undef $pid; undef $fd_pipe; undef $fh_pipe; $startb->configure( -state => 'normal' ); } sub poll { if ( !defined($pid) ) { stop(); return; } ++$count; my $avail = 0; if ( !PeekNamedPipe( $fd_pipe, undef, 0, undef, $avail, undef ) ) { if ( $^E == ERROR_BROKEN_PIPE ) { stop(); return; } die $^E; } return if !$avail; sysread($fh_pipe, my $buf, $avail) or die $!; $text->PRINT($buf); } { $mw = MainWindow->new( -background => 'gray50' ); $text = $mw->Scrolled('Text')->pack(); $startb = $mw->Button( -text => 'Start', -command => \&start, )->pack(); my $label = $mw->Label( -textvariable => \$count )->pack(); my $stopb = $mw->Button( -text => 'Exit', -command => sub { stop(); exit(); }, )->pack(); MainLoop(); }
Update: Simplified the code slightly by using the code from Re^8: ... (Proof!) instead of the code from Re^2: Non-blocking Reads from Pipe Filehandle.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Please suggest a non-forking way to do this (OS: windows) (solution)
by zentara (Cardinal) on Oct 01, 2008 at 12:59 UTC |