Re: Problems sending to stdin of POE::Wheel::Run-spawned process

2004-12-24 Thread Rocco Caputo
On Thu, Dec 23, 2004 at 04:03:11PM -0800, Dan McCormick wrote:
  I briefly considered whether the wheel should guarantee flushing on
  shutdown, but I decided against it.  Sometimes people may want to shut
  down a client regardless of the input waiting for it.
  
  Maybe the shutdown methods need flush/immediate options?
 
 That would definitely be convenient.  Would it be as simple as this?  It
 works with the test case I sent earlier.  I'll re-submit it with a doc patch
 if it looks ok.
 
 --- Run.pm  Mon Nov 15 23:31:17 2004
 +++ Run.pm.new  Thu Dec 23 15:28:09 2004
 @@ -859,8 +859,13 @@
  
  # Shutdown the pipe that leads to the child's STDIN.
  sub shutdown_stdin {
 -  my $self = shift;
 +  my ($self, %args) = @_;
 +
return unless defined $self-[HANDLE_STDIN];
 +
 +  if ($args{flush}) {
 +   $self-[DRIVER_STDIN]-flush($self-[HANDLE_STDIN]);
 +  }
  
$poe_kernel-select_write($self-[HANDLE_STDIN], undef);
 
 Dan

Your patch will work in a lot of cases, but it won't work in all of
them.  Consider when flush() is called to write to a full pipe.  It
can't block, so it must return while the driver's buffer contains
data.

A more complete solution would be to check the driver's output buffer
after flush().  If it flushed everything, go ahead and shutdown right
away.  Otherwise set a flag in the wheel, and check it after the usual
flush().

-- 
Rocco Caputo - http://poe.perl.org/


Re: Problems sending to stdin of POE::Wheel::Run-spawned process

2004-12-23 Thread Rocco Caputo
On Wed, Dec 22, 2004 at 09:20:39PM -0800, Dan McCormick wrote:
 
 Whaddya say I submit a doc patch mentioning that (a) it's up to the user to
 flush the buffer (if they want to) when using shutdown_stdin and (b)
 get_driver_out_octets is a handy part of the process.
 
 For that matter, should I take a stab at documenting get_driver_out_octets
 and get_driver_out_messages in POE::Wheel::Run (or POE::Wheel?) since they
 aren't mentioned anywhere?

I'd greatly appreciate doc patches.  I think nobody looks at
POE::Wheel, so the methods probably ought to be documented in each
subclass.

I briefly considered whether the wheel should guarantee flushing on
shutdown, but I decided against it.  Sometimes people may want to shut
down a client regardless of the input waiting for it.

Maybe the shutdown methods need flush/immediate options?

-- 
Rocco Caputo - http://poe.perl.org/


Re: Problems sending to stdin of POE::Wheel::Run-spawned process

2004-12-23 Thread Dan McCormick
 I briefly considered whether the wheel should guarantee flushing on
 shutdown, but I decided against it.  Sometimes people may want to shut
 down a client regardless of the input waiting for it.
 
 Maybe the shutdown methods need flush/immediate options?

That would definitely be convenient.  Would it be as simple as this?  It
works with the test case I sent earlier.  I'll re-submit it with a doc patch
if it looks ok.

--- Run.pm  Mon Nov 15 23:31:17 2004
+++ Run.pm.new  Thu Dec 23 15:28:09 2004
@@ -859,8 +859,13 @@
 
 # Shutdown the pipe that leads to the child's STDIN.
 sub shutdown_stdin {
-  my $self = shift;
+  my ($self, %args) = @_;
+
   return unless defined $self-[HANDLE_STDIN];
+
+  if ($args{flush}) {
+   $self-[DRIVER_STDIN]-flush($self-[HANDLE_STDIN]);
+  }
 
   $poe_kernel-select_write($self-[HANDLE_STDIN], undef);

Dan




Re: Problems sending to stdin of POE::Wheel::Run-spawned process

2004-12-22 Thread Dan McCormick
Ah.  Fascinating.  Thanks!

Whaddya say I submit a doc patch mentioning that (a) it's up to the user to
flush the buffer (if they want to) when using shutdown_stdin and (b)
get_driver_out_octets is a handy part of the process.

For that matter, should I take a stab at documenting get_driver_out_octets
and get_driver_out_messages in POE::Wheel::Run (or POE::Wheel?) since they
aren't mentioned anywhere?

Dan

On 12/21/04 9:57 PM, Rocco Caputo [EMAIL PROTECTED] wrote:

 On Tue, Dec 21, 2004 at 08:39:53PM -0800, Dan McCormick wrote:
 So consider this:
 
 I have a stream of data, which I'm sending to the POE::Wheel::Run process.
 At an arbitrary time I can get a signal that the stream has ended, at which
 point I want to shutdown the process's STDIN.
 
 If I knew the last bit of data sent was going to be the last bit of data, I
 could set a flag as I send it to the POE::Wheel::Run process, and then the
 next StdinEvent could call stdin_shutdown.  But I don't know which bit of
 data is going to be the last.
 
 So when I receive the signal to shutdown STDIN, I don't know if the STDIN
 buffer is flushed or not (do I?).  I can set a flag, but if it's already
 flushed, the StdinEvent will never get called.
 
 It seems I need a way to tell if there's anything pending in the buffer.
 
 Checking $wheel-get_stdin_filter-get_pending() seems like a good bet, but
 doesn't seem to be working -- it always seems to return false, even though
 if I then call stdin_shutdown the data never arrives at my process.
 
 Any suggestions?  Am I missing something?
 
 Yep!
 
 The child's STDIN is the wheel's otput buffer.  Whenever you put()
 something to a wheel, you're writing whole things (where thing is
 defined by the filter you're using).
 
 Since things are sent whole, filters don't need to buffer them for
 output.  Rather, they convert them and return them right away.  The
 serialized things are sent to the driver for flushing in a little
 while.
 
 Anyway, most wheels have get_driver_out_octets() methods that tell you
 how many octets are waiting in the driver to be flushed.  I think
 that's what you're looking for.




Re: Problems sending to stdin of POE::Wheel::Run-spawned process

2004-12-21 Thread Rocco Caputo
On Mon, Dec 20, 2004 at 10:44:23PM -0800, Dan McCormick wrote:
 
 Shouldn't the code below print 1, 2, 3, 4 on separate lines to the file
 /tmp/test.txt?
 
 If I comment out lines 537-538 of POE::Wheel::Run.pm, namely:
 
   $poe_kernel-select_pause_write($self-[HANDLE_STDIN])
 unless ($self-[OCTETS_STDIN]);
 
 ... things work as (I) expected.  Some cursory debugging suggests POE isn't
 flushing the buffer when the state returns, as the docs indicate.

They don't quite work the way I expect, but I think you'll agree that
teh problem's over in shutdown_stdin() (around line 872):

  # Shutdown the pipe that leads to the child's STDIN.
  sub shutdown_stdin {
my $self = shift;
return unless defined $self-[HANDLE_STDIN];

$poe_kernel-select_write($self-[HANDLE_STDIN], undef);

eval { local $^W = 0; shutdown($self-[HANDLE_STDIN], 1) };
close $self-[HANDLE_STDIN] if $@;
  }

The problem's fairly obvious.  Your test case calls put() to prime the
STDIN buffer, then it calls shutdown_stdin() to close STDIN.
Unfortunately, the wheel also stops select_write() for the handle.
That prevents the buffer from ever being flushed.

The proper thing to do is perhaps to set a shutdown flag if there is
pending input for the child process, and do the actual shutdown when
the input has flushed.

 Also, even with the commented-out lines, it looks like I still need the
 'doit' and 'shutdown' events to be separate (i.e., combining everything into
 the _start event doesn't work).  Is that behavior intentional?

I think it's creating a race condition where your expected behavior
occurs.  It seems to be working only by coincidence.

-- 
Rocco Caputo - http://poe.perl.org/


Re: Problems sending to stdin of POE::Wheel::Run-spawned process

2004-12-21 Thread Dan McCormick
Hmmm.  Interesting.

So consider this:

I have a stream of data, which I'm sending to the POE::Wheel::Run process.
At an arbitrary time I can get a signal that the stream has ended, at which
point I want to shutdown the process's STDIN.

If I knew the last bit of data sent was going to be the last bit of data, I
could set a flag as I send it to the POE::Wheel::Run process, and then the
next StdinEvent could call stdin_shutdown.  But I don't know which bit of
data is going to be the last.

So when I receive the signal to shutdown STDIN, I don't know if the STDIN
buffer is flushed or not (do I?).  I can set a flag, but if it's already
flushed, the StdinEvent will never get called.

It seems I need a way to tell if there's anything pending in the buffer.

Checking $wheel-get_stdin_filter-get_pending() seems like a good bet, but
doesn't seem to be working -- it always seems to return false, even though
if I then call stdin_shutdown the data never arrives at my process.

Any suggestions?  Am I missing something?

Thanks,
Dan

On 12/21/04 3:18 PM, Rocco Caputo [EMAIL PROTECTED] wrote:

 On Mon, Dec 20, 2004 at 10:44:23PM -0800, Dan McCormick wrote:
 
 Shouldn't the code below print 1, 2, 3, 4 on separate lines to the file
 /tmp/test.txt?
 
 If I comment out lines 537-538 of POE::Wheel::Run.pm, namely:
 
   $poe_kernel-select_pause_write($self-[HANDLE_STDIN])
 unless ($self-[OCTETS_STDIN]);
 
 ... things work as (I) expected.  Some cursory debugging suggests POE isn't
 flushing the buffer when the state returns, as the docs indicate.
 
 They don't quite work the way I expect, but I think you'll agree that
 teh problem's over in shutdown_stdin() (around line 872):
 
   # Shutdown the pipe that leads to the child's STDIN.
   sub shutdown_stdin {
 my $self = shift;
 return unless defined $self-[HANDLE_STDIN];
 
 $poe_kernel-select_write($self-[HANDLE_STDIN], undef);
 
 eval { local $^W = 0; shutdown($self-[HANDLE_STDIN], 1) };
 close $self-[HANDLE_STDIN] if $@;
   }
 
 The problem's fairly obvious.  Your test case calls put() to prime the
 STDIN buffer, then it calls shutdown_stdin() to close STDIN.
 Unfortunately, the wheel also stops select_write() for the handle.
 That prevents the buffer from ever being flushed.
 
 The proper thing to do is perhaps to set a shutdown flag if there is
 pending input for the child process, and do the actual shutdown when
 the input has flushed.
 
 Also, even with the commented-out lines, it looks like I still need the
 'doit' and 'shutdown' events to be separate (i.e., combining everything into
 the _start event doesn't work).  Is that behavior intentional?
 
 I think it's creating a race condition where your expected behavior
 occurs.  It seems to be working only by coincidence.