perl script throws compilation error ONLY when running with -d switch - perl

I have a perl script, that runs fine EXCEPT when I try to run it in the debug mode with the -d switch.
When I use the -d switch, I get a compilation error like:
Loading DB routines from perl5db.pl version 1.33
Editor support available.
Enter h or `h h' for help, or `perldoc perldebug' for more help.
main::(..\..\bin\testnbestrover1.pl:23):
23: binmode STDOUT, ":utf8";
Access is denied.
Unknown error
Compilation failed in require at //fbl/NAS/PUB/RapTools/Perl64/lib/Term/ReadLine
/Perl.pm line 65.
at //fbl/NAS/PUB/RapTools/Perl64/lib/Term/ReadLine/Perl.pm line 65
Term::ReadLine::Perl::new('Term::ReadLine', 'perldb', 'GLOB(0x382418)',
'GLOB(0x322c30)') called at //fbl/NAS/PUB/RapTools/Perl64/lib/perl5db.pl line 60
68
DB::setterm called at //fbl/NAS/PUB/RapTools/Perl64/lib/perl5db.pl line
2241
DB::DB called at ..\..\bin\testnbestrover1.pl line 23
Attempt to reload Term/ReadLine/readline.pm aborted.
Compilation failed in require at //fbl/NAS/PUB/RapTools/Perl64/lib/Term/ReadLine
/Perl.pm line 65.
END failed--call queue aborted at ..\..\bin\testnbestrover1.pl line 65.
at ..\..\bin\testnbestrover1.pl line 65
This does not happen when I run the script without the -d switch. Any ideas about what may be going wrong here?
Thanks!
EDIT:
The same error in Term/ReadLine/Perl.pm line 65 occurs if I comment out the binmode STDOUT, ":utf8"; statement.
Upon searching for this specific error on the web, I found someone else had faced the same error when they were redirecting their STDOUT to a file using the ">" operator. Turns out, my perl command was doing the same thing, and when I removed it, the debugger works fine.
Seems to be a problem with the specific perl debugger (i.e., per5db.pl version 1.33)?

The stacktrace indicates that the problem comes from Term::ReadLine::Perl which is loaded from the debugger. So no debugging -> no loading of debugger -> no loading of Term::ReadLine::Perl -> no error.
From looking at Term::ReadLine::Perl I guess that the problem is in the line where it tries to load Term::ReadLine::readline which tries to do some stuff with STDIN, STDOUT etc to use it as a terminal. Because this effectively means, that some byte sequences have a special meaning (escape and control codes, like to reset terminal, switch line mode, echo etc) this might infere with your binmode STDOUT settings.

Related

Perl Cleartool Accept Statement

I am using the following code to execute the ClearCase statement "Accept" from a perl script.
$acceptA = `accept $Component`;
After execution, inside my perl script, the value of $acceptA is blank.
The text displayed on the screen during execution of this line is : "ERROR You do not have permissions to ACCEPT this work."
How do I read this line? I thought it would return into the variable $acceptA as it does with the "cleartool checkin" command?
As i do not know ClearCase and how that accept works, i can only guess. Seeing how it is an error message, it might be written to STDERR instead of STDOUT and backticks only capture STDOUT of the command executed.
In that case, redirecting the commands STDERR to STDOUT would work. Try
$acceptA = `accept $Component 2>&1`
and see if that works in capturing the output in case of error as well.
I eventually redirected SYSERR to an output file which I could read/write.
open STDERR, ">/ellipse/el6.3.3_ry_sup/src/0/$logfile"
All the error messages that was displayed on the screen as part of the system command, went into $logfile.
I was also able to add to SYSERR with the following:
print STDERR "\nAccepting $Component";
Thanks for all the help.

Perl not executing command when in debugger or as a Win32::Daemon

Synopsis
I execute a shell command from Perl and when run from the command line it works, but when run in the debugger it does not work. Running it as a Win32::Daemon shows the same behaviour.
The Source Code
I execute a command either with backticks
print `$cmd`
or like this:
open FH, "$cmd |" or die "Couldn't execute $cmd: $!\n";
while(defined(my $line = <FH>)) {
chomp($line);
print "$line\n";
}
close FH;
The command reads like this:
$cmd = '"C:\path\to\sscep.exe" getca -f "C:\path\to\config\capi_sscep.cnf"'
Even creating a small test script that just executes this command does only work if run from command line.
The System
Windows x64
Active Perl v5.16.0, MSWin32-x64-multi-thread
Eclipse Juno 20120614-1722
What works
I works to open an administrator prompt (necessary for script execution) and to:
perl script.pl
Output gets printed to screen, $? is 0.
What does not work
Starting Eclipse and running a debug session with the same perl script.pl call.
Also not working is adding a service and executing the command (created with Win32::Daemon). The daemon itself is working perfectly fine and starting the perl script as expected. Only the command does not get executed. $? is 13568 or 53 if shifted with $? >> 8, no output gets printed. The exit code does not belong to the program.
Further Details
The tool I am calling is called sscep and is extended by me. It uses the OpenSSL API and loads the capi engine (Windows CryptoAPI). But the command itself does at least print output before any serious action starts. I can happily provide the source code for this, but I doubt it will help.
I was able to narrow this further down: The problem only exists in the combination of the Perl program (CertNanny) and the binary (sscep). Calling dir inside CertNanny works, calling sscep in a test Perl script works, too. So what could possibly be done in Perl to break a single binary from being called...?
Any ideas where this problem might originate from or how I can possibly narrow it down?
Here is what I believe the problem to be: when you run your program on the command line, the system() command goes through the shell (cmd.exe); when you run your program elsewhere, it does not. Unfortunately, the two methods handle command line arguments differently. Here is an article that seems like it should help you solve the problem.
In my experience, this sort of thing is a mess in Windows. I have had trouble with this issue in Perl, also.

Finding the source of a perl taint mode error

When running a perl CGI script in taint mode, I get an error of the form...
Insecure dependency in some_function while running with -T switch at (eval some_line) line some_other_line.
Compilation failed in require at my-script.cgi line 39.
BEGIN failed--compilation aborted at my-script.cgi line 39.
my-script.cgi line 39 is a use statement for a perl module which does not itself use eval or some_function, but presumably uses another library which does. The some_line and some_other_line line numbers don't seem to make sense in either my-script.cgi or the library which is 'use'd on line 39 of my-script.cgi.
Given this error, how can I track down where the taint error is occurring?
I've tried setting a new die signal handler which should print a stack trace, i.e.
$SIG{ __DIE__ } = sub { require Carp; Carp::confess(#_); };
but this seems to have no effect on the error. Perhaps this is the wrong signal to be trapping, not happening early enough, or something more complex is required.
Carp::Always works fine with exceptions raised by taint checks. Example output:
$ perl -MCarp::Always -T blah.pl
Insecure dependency in sprintf while running with -T switch at blah.pl line 6
main::foo() called at blah.pl line 8
main::bar() called at blah.pl line 10
I use Devel::SimpleTrace a lot these days for debugging and it recently helped me find a taint bug when using Archive::Zip.
However, I don't know if it would have worked in your case since it is essentially setting the same sig handler that you used.

How do I propagate an exception thrown by croak in forked child to parent/foreground process?

Throwing an exception via croak in a forked child process seems to print the error as a background process would. That is, it clobbers the shell prompt.
If I die instead of croak, the the error message pops up as a foreground process. I've trying to find out why that is in the Carp documentation without any luck.
Here's what I mean. The croak version:
$ perl Wrapper.pm
$ error: ... does not exist at Wrapper.pm line 624
The die version:
$ perl Wrapper.pm
error: ... does not exist at Wrapper.pm line 515.
I tried trapping the fork and printing $# to STDERR and exiting, but that didn't have an effect. Any ideas? I'd like to be able to use croak in this particular case.
Although my code is quite a bit more convoluted, here is how you can reproduce this behavior:
$ perl -MCarp -e 'unless (fork) {croak "child"}'
$ child at -e line 1
<- cursor blinking here. Pressing enter gives me a new prompt:
$
$ perl -e 'unless (fork) {die "child"}'
child at -e line 1.
$
Solved: cjm got it:
$ perl -e '$SIG{__DIE__} = sub {sleep 1}; unless (fork) {die "child"}'
$ child at -e line 1.
Thanks for the help!
I'm pretty sure it's just a timing issue. The die version is slightly faster, so it has a better chance of outputting the error message before the shell can print the next prompt. When I try running your examples, the croak version usually gets printed after the prompt, but occasionally it comes before the prompt. The die version pretty consistently comes before the prompt.

Why does TextMate always complain 'Can't find string terminator '"'' when it runs a Perl script?

I have a long-ish Perl script that runs just fine, but always gives this warning:
Can't find string terminator '"' anywhere before EOF at -e line 1
I've read elsewhere online that this is because of a misuse of single or double quotes and the error generally stops the script from running, but mine works. I'm pretty sure I've used my quotes correctly.
Is there anything else that could cause this warning?
EDIT:
I'm running the script via TextMate, which may be spawning a new Perl process to run my script.
I actually get the error when I run simple scripts as well, like this one:
#!/usr/bin/perl -w
use strict;
use warnings;
print "Hello world.";
Yes, you are right, your script does that in TextMate when I try it too.
Simple solution: don't run it using TextMate; just use the command line:
cd Projectdirectory
chmod +x myscript.pl
./myscript.pl
Hello world
More complex solution: tell TextMate that their application is broken and wait for them to fix it. The error is coming from some other Perl script that TextMate is invoking. Even a completely blank file run as Perl in TextMate fails with this error.
-Alex
The "at -e line 1" bit means it's coming from a one-liner. I suspect your long script is somewhere starting a separate perl process (possibly indirectly), and that perl is what is giving the error (and not doing whatever it is supposed to do.)
Start the debugger by doing
perl -d ./youscript.pl
Then keep pressing n[ENTER] (or just ENTER after you press n once) until you see the warning - the line that was just executed is your culprit. n stands for the next debugger directive btw.