in reply to Re: Re: Filter::Handle - Deep Recursion Error
in thread Filter::Handle - Deep Recursion Error

The following works for me?

Update: Note: I had to change the anonymous sub slightly to use @_ instead of $_[0]. Only the first argument to the print statement was being output.

#! perl -slw use strict; use Filter::Handle; open FH1, '>', 'my.log' or die $!; open FH2, '>', 'myother.log' or die $!; tie *FH1, 'Filter::Handle', \*FH2, sub{ @_ }; ## << NOTE THE CHANGE!!! print FH1 'Hello world!', $_ for 1 .. 10;

The test

P:\test>del *.log P:\test>dir *.log Volume in drive P is Winnt Volume Serial Number is D822-5AE5 Directory of P:\test File Not Found P:\test>262848 P:\test>dir *.log Volume in drive P is Winnt Volume Serial Number is D822-5AE5 Directory of P:\test 03/06/04 04:32a 0 my.log 03/06/04 04:32a 151 myother.log 2 File(s) 151 bytes 387,018,752 bytes free P:\test>type myother.log Hello world!1 Hello world!2 Hello world!3 Hello world!4 Hello world!5 Hello world!6 Hello world!7 Hello world!8 Hello world!9 Hello world!10

That said, I'm not quite sure why you would do this? If all the print statements you wish to re-direct already print to an filehandle, why not just open the desired output file as that handle?


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


Replies are listed 'Best First'.
Re: Filter::Handle - Deep Recursion Error
by cadphile (Beadle) on Jun 19, 2003 at 23:55 UTC
    I actually work with bayruds, and we were sharing this code snippet, but I'm having a slightly different problem with this. The deep recursion is only showing up in Perl-5.8.0. Previous versions do not have this problem.

    Secondly, we're using the Filter::Handle module to split STDERR to both a logfile and to the terminal. For this I have been using (until switching to Perl-5.8.0) the following code snippet:

    use Filter::Handle qw/subs/; ## $LOG_FH is a FileHandle reference... Filter \*STDERR, sub { local $_ = @_; if (defined $LOG_FH) {print $LOG_FH "STDERR: $_";} $_ }; ## Need a signal handler to capture warnings from carp ## and warn which are not captured by Filter::Handle ## (but by capturing ourselves and printing to STDERR, ## they do get picked up by Filter::Handle)... $SIG{__WARN__} = sub { local $_ = "@_"; print STDERR $_; };
    I don't want to just tie STDERR to the $LOG_FH filehandle, I want to print to both STDERR and the filehandle.

    Beginning with Perl-5.8.0, any output to STDERR, either explicitly or from Perl (e.g. uninitialized variable) results in a deep recursion error. Any thoughts about this?? Why is this happening only in Perl-5.8.0?
    thanks,
    -Cadphile

      Okay. Here's what I think is going on, based upon my observations and some reading. I say what comes next with a great deal of trepidation because not only is the author of Filter::Handle well respected, but in the bottom of the pod for the module he thanks no less a list of PM luminaries as tilly, chromatic and merlyn!

      There seems to be a fundemental design flaw in Filter::Handle.

      What the module does is to tie the handle supplied (through whichever of its 3 interfaces) to itself. Then, whenever print or printf is called on the tied handle, the tie magic ensures that the PRINT or PRINTF routines within then module get called. It then calls the sub you pass in when you intialise the filtering, and passing you the arguments that would have been passed to print or printf and gives you the opportunity to modify them before returning them. It then calls print or printf on the tie'd handle passing the modified arguments.

      The problem is, that the handle it is using is the same one as you did, which is still tied, and so it recursively calls itself and then calls you and then calls print or printf on the same tied handle which means it recurses into itself again....ad nauseum.

      I cannot explain why this didn't happen in 5.6. By my logic, it should, but if it had, then the module would never have made it onto CPAN as is.

      At first, I thought that this was to do with you $SIG{__WARN__} handler. I remembered from the perl58delta that as of 5,8, signals were now "safe", and to quote the docs,

      Perl used to be fragile in that signals arriving at inopportune moment +s could corrupt Perl's internal state. Now Perl postpones handling of + signals until it's safe (between opcodes). This change may have surprising side effects because signals no longer + interrupt Perl instantly. Perl will now first finish whatever it was + doing, like finishing an internal operation (like sort()) or an exte +rnal operation (like an I/O operation), and only then look at any arr +ived signals (and before starting the next operation)

      but this was a red-herring easily dismissed by removing the WARN handler. The recursion still occurs under 5.8.

      However, there were also some fairly extensive changes made to the IO in 5.8, not least of which was the move to PerlIO by default.

      My gut feeling is that Filter::Handle only worked in 5.6 because of a bug that has either been fixed or bypassed in the move to 5.8. I don;t like drawing the conclusion because I can't think of any easy way to prove it. Perhaps if someone has a build of 5.6(.1) that was built with PerlIO, they could try it and see if that also goes into recursion. My best 'evidence' for my conclusion is just the logic of the thing.

      If I tie a handle, and intercept prints to that handle, and then invoke print on that same handle from within the PRINT handler itself, how could I NOT end up recursing back into myself?

      Nothing has changed between the call to print on the tied handle and when I call print on that same tied handle from within the handler. Unless perl has some additional magic to temporarially untie a tied handle whilst in the handler?

      Of course, this doesn't explain why it doesn't go into recursion under 5.6...but my only explaination for that is a bug in 5.6 that allowed it to 'work'!

      Sorry I cannot suggest an immediate workaround for your problem.

      BrowserUk currently sitting here feeling the presence of the Sword of Damocles hanging above me:)


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller