How can I disable Perl warnings for svnnotify? - perl

I'm using svnnotify. It works (sends email and all that) but it always outputs some error messages, such as
Use of uninitialized value in substr at /usr/lib/perl5/site_perl/5.8.8/SVN/Notify.pm line 1313.
substr outside of string at /usr/lib/perl5/site\_perl/5.8.8/SVN/Notify.pm line 1313.
Use of uninitialized value in index at /usr/lib/perl5/site\_perl/5.8.8/SVN/Notify.pm line 1313.
Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/site\_perl/5.8.8/SVN/Notify.pm line 1314.
I've tried running it with > /dev/null but no luck. I've tried running it > bla and file bla comes up empty, and the output is shown on screen. Since svnnotify does not have a quiet switch, how can I do this?

It looks like this happens when there is no log message for the commit. Some users may need to have a LART session to fix that. Barring that, the right thing to do is fix the SVN::Notify module and submit the patch to the SVN::Notify RT queue, but too late, I've already submitted the ticket.
Here's the patch:
diff --git a/lib/SVN/Notify.pm b/lib/SVN/Notify.pm
index 3f3672b..5387dd2 100644
--- a/lib/SVN/Notify.pm
+++ b/lib/SVN/Notify.pm
## -1308,7 +1308,7 ## sub prepare_subject {
}
# Add the first sentence/line from the log message.
- unless ($self->{no\_first\_line}) {
+ if (!$self->{no\_first\_line} and defined $self->{message}[0] and length $self->{message}[0] )
# Truncate to first period after a minimum of 10 characters.
my $i = index substr($self->{message}[0], 10), '. ';
$self->{subject} .= $i > 0
I think that takes care of the warnings, but I suspect it's only a band-aid because the design around $self->{no\_first\_line} seems dodgy.

While the accepted answer certainly works, it isn't (in my opinion) the best answer, because one day you're going to have to maintain this code (or worse, someone else will), and getting it to run with no warnings will make your code that much better. Given the warnings, it looks like the problem isn't you, but it's hard (but not impossible) to imagine that a module in version 2.79 would give errors. Maybe your copy of SVN::Notify is old? Maybe your code (or someone's code) is mucking with the module's internals? It's hard to tell with the few warnings I can see, and I have a feeling there's a bit more to this problem than meets the eye.

The error is printed on stderr, you can redirect it to /dev/null with 2> /dev/null. Alternatively you can make it not use perl -w.

Related

Don't stop perl on: Quantifier in {,} bigger than 32766 in regex

The question Retain newlines for POD in case of PPR::uncomment was solved in the answer by defining a new method decomment2 that leaves the newlines properly. All works quite well, but now I have a file to process with a very big HERE document (far to big to publish here so unfortunately a link to an external site): https://github.com/openssl/openssl/blob/master/crypto/bn/asm/ppc.pl
When this file is processed through the PPR::decomment2 I get the message:
Quantifier in {,} bigger than 32766 in regex; marked by <-- HERE in m/(?s:.{ <-- HERE 39303})/ at /home/User/perl5/lib/perl5/Doxygen/Filter/Perl.pm line 1222.
Line 1222 is: $str =~ m{ \A (?&PerlDocument) \Z in the PPR::decomment2 method.
At that moment, the Perl process terminates.
Is there a way to increase this "32766" limit, i.e 2**15-2, in some way?
Is there a way not to terminate the Perl process but set the PPR::ERROR or another flag, so this can be processed in the code?
As a point of information, the max value was doubled in Perl 5.30 to 65534.
I did some research and passed by the eval possibility.
Is there anything against a construct like:
eval {
my $mystr = PPR::decomment2($str)
# do some local dependent stuff
};
if ($#) {
# do the local handling if the error
}
Is there anything against a construct like this?
Edit (April 23, 2013): a patch has been made by the maintainer of the PPR package (Damian Conway). The package number is 25.

How to detect unreachable code in Perl conditional which always evaluates to false?

I'm new to Perl, and am currently tasked with tidying and maintaining a large and pretty messy Perl project. I'm using perl-critic to help me detect issues in the code (and also to teach me best practices).
The existing code has places where the coder has created unreachable code. For instance, they added '&& 0' as a lazy way of commenting out some of the code branches:
if ($req->param('donut') && 0) {
unreachable code...
} else {
always branches to here...
}
I'd hoped that perl or Critic would warn me about unreachable code in such instances (where a conditional has a constant value evaluating to false), but it doesn't.
Is there a tool or a piece of script I could use which can reliably detect this kind of thing?
Obviously I could search for '&& 0' in the source but there are a number of ways that the coder could have created unreachable code besides appending '&& 0' to an if statement.
Using B::Deparse, you can detect unreachable code in some situations:
perl -MO=Deparse -e 'if (0 && $x) {print 1} else {print 2}'
do {
print 2
};
-e syntax OK
It's not so easy if the 0 is not the first condition, though:
perl -MO=Deparse -e 'if ($x && 0) {print 1} else {print 2}'
if ($x and 0) {
print 1;
}
else {
print 2;
}
-e syntax OK
Why is it different? Well, if 0 comes last, all the conditions before it must be checked. They can have side-effects which will still happen. Also, && forces a scalar context, so it can change the behaviour of the code called when evaluating the condition.
This doesn't explain why the block itself isn't compiled away, sorry. My guess would be it just seemed too complicated.
As per choroba's answer, B::Deparse will be able to show you cases where the code is so obviously unreachable that the Perl compiler optimizes it away. But, in the general case it's impossible to detect. The following code includes an effectively unreachable block.
use 5.006;
if ($] < 5) { ... }
Because $] is a variable which returns the currently running version of Perl, which is guaranteed to be at least 5.006 by the use line. But you'd need some pretty clever techniques to figure that out using static analysis of the source code. (As an aside, although an unusual thing to do, it is possible to alter the value of $] at run-time — see Acme::Futuristic::Perl — in which case the code will become reachable.)
If you have a decent test suite for your code, Devel::Cover may be useful. You set the environment variable PERL5OPT to -MDevel::Cover, then run your test suite (note it will run a little slower than usual), then run the command cover which will produce a pretty HTML report. This report will highlight which subs were not executed, which branches were never used, etc.

Perl operator: $|++; dollar sign pipe plus plus

I'm working on a new version of an already released code of perl, and found the line:
$|++;
AFAIK, $| is related with pipes, as explained in this link, and I understand this, but I cannot figure out what the ++ (plus plus) means here.
Thank you in advance.
EDIT: Found the answer in this link:
In short: It forces to print (flush) to your console before the next statement, in case the script is too fast.
Sometimes, if you put a print statement inside of a loop that runs really really quickly, you won’t see the output of your print statement until the program terminates. sometimes, you don’t even see the output at all. the solution to this problem is to “flush” the output buffer after each print statement; this can be performed in perl with the following command:
$|++;
[update]
as has been pointed out by r. schwartz, i’ve misspoken; the above command causes print to flush the buffer preceding the next output.
$| defaults to 0; doing $|++ thus increments it to 1. Setting it to nonzero enables autoflush on the currently-selected file handle, which is STDOUT by default, and is rarely changed.
So the effect is to ensure that print statements and the like output immediately. This is useful if you're outputting to a socket or the like.
$| is an abbreviation for $OUTPUT_AUTOFLUSH, as you had found out. The ++ increments this variable.
$| = 1 would be the clean way to do this (IMHO).
It's an old idiom, from the days before IO::Handle. In modern code this should be written as
use IO::Handle;
STDOUT->autoflush(1);
It increments autoflush, which is most probably equivalent to turning it on.

Bizarre copy of UNKNOWN in subroutine entry

I'm hitting a bug in the SVN perl module when using git:
Bizarre copy of UNKNOWN in subroutine entry at
/usr/lib/perl5/vendor_perl/SVN/Base.pm line 80.
And I'm not quite sure if this is a perl bug or a subversion bug. This is the relevant part:
# insert the accessor
if (m/(.*)_get$/) {
my $member = $1;
*{"${caller}::$1"} = sub {
&{"SVN::_${pkg}::${prefix}${member}_". # <<<< line 80
(#_ > 1 ? 'set' : 'get')} (#_)
}
}
(full source)
What is a "Bizarre copy"? And whose fault is it?
Edit: software versions
subversion 1.6.15-1
perl 5.14.0-1
Resolution: This happens when you compile with incompatible flags:
https://groups.google.com/d/msg/subversion_users/EOru50ml6sk/5xrbu3luPk4J
That perldoc gives you the short answer, but a brief STFW session yields a little more detail. This is basically evidence of a smashed stack in Perl.
Trivial example:
#!/usr/bin/perl
my #A = 1..5;
sub blowUp {
undef #A;
my $throwAway = {};
print for #_; # <== line 6
}
blowUp(#A);
__END__
bash$ ./blowitup
Bizarre copy of HASH in print at ./blowitup line 6.
And to make it that much more entertaining, without the $throwAway assignment, it's an invisible error (though under 'use warnings' it will at least still tell you that you're trying to access an uninitialized value). It's just when you make a new assignment that you see the strange behavior.
Since #_ is essentially lexically scoped to the subroutine, and arguments are passed by reference, that little subroutine basically pulls the rug out from under itself by undef'ing the thing that #_ was pointing to (you get the same behavior if you change the undef to an assignment, fwiw). I've found a number of postings on perl5-porters that mention this as an artifact of the fact that items on the stack are not reference counted and therefore not cleanly freed.
So while I haven't looked through all of the code in your full source in depth, I'll go ahead and guess that something in there is messing with something that was passed in on #_ ; then when #_ is referenced again, Perl is telling you that something's rotten in Denmark.
The immediate problem is a bug in the script/module, iow. The deeper issue of Perl not reference counting these items is also there, but I suspect you'll have better luck fixing the module in the short term. :-)
HTH-
Brian
A "Bizarre copy" occurs when Perl's stack is corrupted or contains non-scalars. It occurs as the result of bugs in Perl itself or in XS modules. (Brian Gerard's example exercises one of a long list of known bugs related to the stack not being ref-counted.)
You could isolate the problem by adding the following to the anon sub:
warn("Calling SVN::_${pkg}::${prefix}${member}_".(#_ > 1 ? 'set' : 'get')."...");
You might even want to emit a stack trace, but you might have to build it yourself using caller to avoid triggering the panic when building the stack trace.
Probably a perl bug. SVN::Base has XS components, but the error is occurring in pure-perl code and it's my opinion that perl should never allow it to happen. However, it's possible that there's some weird XS in SVN::Base that's tweaking it.
Best idea: file it against Subversion subcomponent bindings_swig_perl and perlbug both.

In Perl, is there any way to tie a stash?

Similar to the way AUTOLOAD can be used to define subroutines on demand, I am wondering if there is a way to tie a package's stash so that I can intercept access to variables in that package.
I've tried various permutations of the following idea, but none seem to work:
{package Tie::Stash;
use Tie::Hash;
BEGIN {our #ISA = 'Tie::StdHash'}
sub FETCH {
print "calling fetch\n";
}
}
{package Target}
BEGIN {tie %Target::, 'Tie::Stash'}
say $Target::x;
This dies with Bad symbol for scalar ... on the last line, without ever printing "calling fetch". If the say $Target::x; line is removed, the program runs and exits properly.
My guess is that the failure has to do with stashes being like, but not the same as hashes, so the standard tie mechanism is not working right (or it might just be that stash lookup never invokes tie magic).
Does anyone know if this is possible? Pure Perl would be best, but XS solutions are ok.
You're hitting a compile time internal error ("Bad symbol for scalar"), this happens while Perl is trying to work out what '$Target::x' should be, which you can verify by running a debugging Perl with:
perl -DT foo.pl
...
### 14:LEX_NORMAL/XOPERATOR ";\n"
### Pending identifier '$Target::x'
Bad symbol for scalar at foo.pl line 14.
I think the GV for '::Target' is replaced by something else when you tie() it, so that whatever eventually tries to get to its internal hash cannot. Given that tie() is a little bit of a mess, I suspect what you're trying to do won't work, which is also suggested by this (old) set of exchanges on p5p:
https://groups.google.com/group/perl.perl5.porters/browse_thread/thread/f93da6bde02a91c0/ba43854e3c59a744?hl=en&ie=UTF-8&q=perl+tie+stash#ba43854e3c59a744
A little late to the question, but although it's not possible to use tie to do this, Variable::Magic allows you to attach magic to a stash and thereby achieve something similar.