Re: Problems sending to stdin of POE::Wheel::Run-spawned process
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
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
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
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
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
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.