emeitner has asked for the wisdom of the Perl Monks concerning the following question:

I am working on a very simple script to query an LDAP server for a list of users. I found that the script fails randomly at different places, usually the bind() or search() calls. It is utterly frustrating that when I use the debugger(perl -d script.pl), the script works flawlessly.

I am beginning to suspect that Perl and its libraries/modules on this system(UltraSPARC, Debian/woody) are flawed in some way.

The LDAP server is operational. The LDAP on the Sparc machine is functional - it is used for logon authentication. I just want to see where the script is failing so I can get an idea of where to look next.Any suggestions?

  • Comment on Perl debugger fixes bug, now i've got a perl debugger to get rid of.

Replies are listed 'Best First'.
Re: Perl debugger fixes bug, now i've got a perl debugger to get rid of.
by leriksen (Curate) on Feb 23, 2004 at 00:54 UTC
    I would suspect a timing issue - when in 'production' mode, occassionally the timing of things causes a failure - a slightly delayed socket connection, a signal that gets delayed etc. When in debug mode, with everything running slower, the critical points for this behaviour get spread out and are no longer an issue.

    I'd try getting better feedback from your script, in production mode, when the failure occurs, using Data::Dumper, Carp etc to report verbosely about your code's state. If you can't provoke the error at will, you need to get as much info as possible when it does happen.

    Also, trap and test the return code of everything - and I mean everything.

    Try writing your own signal handlers too, if that seems appropriate - stuff like

    $SIG{'INT'} = &int_handler; sub int_handler { ...verbose state printing here... }

    +++++++++++++++++
    #!/usr/bin/perl
    use warnings;use strict;use brain;

Re: Perl debugger fixes bug, now i've got a perl debugger to get rid of.
by Old_Gray_Bear (Bishop) on Feb 22, 2004 at 21:17 UTC
    Another thought is to reduce the debug level you specify in your bind() parameters. You may be timing out the connection while the server side is generating a few metric tons of 'debugging' data. FWIW, I tried the LDAP debug levels exactly once, because I wanted to see what it gave me. 'debug=>1' generated over 1000 lines of response, and that was for a successful bind(}! I don't want to know how much I get back for level 15.

    ----
    I Go Back to Sleep, Now.

    OGB

      I have already run it with the debugging turned off. There was no change in the behavior. The same script on another machine works with it set to maximum.

      Calling sync() before bind() and search() produces: Can't use an undefined value as a HASH reference at /usr/share/perl5/Net/LDAP.pm line 696, <DATA> line 225.

      The docs say that sync() should accept null arguments....

        Could you produce and post a small sample program that exhibits this behaviour?

        From looking at the source, I believe that $ldap->{net_ldap_mesg} does not exist/is not filled/is undef. Whether this makes sense when you call $ldap->sync(), I don't know, but it would help in debugging the error. Maybe you need to call some other method before you can call sync()? For example if you have no outstanding messages?

Re: Perl debugger fixes bug, now i've got a perl debugger to get rid of.
by kutsu (Priest) on Feb 22, 2004 at 19:56 UTC

    can't help you too much without seeing any code

    Update: Logic errors maybe present in your code which no debugger will pick-up can't tell if we can't see the code

    "Cogito cogito ergo cogito sum - I think that I think, therefore I think that I am." Ambrose Bierce

      Code or no code, the fact remains that the script behaves differently when run in the debugger.
      #!/usr/bin/perl -w use Net::LDAP; use strict; my $ldap = Net::LDAP->new( "ldap://server/", debug=>15, version=>3, async => 1 , onerror => 'warn' ); die "new(): $@" if !$ldap; my $result = $ldap->bind(); die "bind(): $@\n" if $result->code; $result = $ldap->search( base => "dc=zzzz,dc=com", filter => "(&(objectclass=posixAccount) )", attrs=>['uid'] ); die "search(): $@\n" if $result->code; print "Results:\n"; foreach my $entry ( $result->entries) { $entry->dump; } $ldap->unbind(); $ldap->disconnect();
Re: Perl debugger fixes bug, now i've got a perl debugger to get rid of.
by bean (Monk) on Feb 22, 2004 at 20:12 UTC
    Ah - you've got a quantum bug there (a bug that changes under observation/measurement). I suggest reverting to more primitive debugging techniques, i.e. adding "print" statements around the suspected buggy code. Those statements may fix the bug the same way using the debugger does, but at least you'll have removed the debugger from the equation.

    Update

    Never mind the above advice - your code is too straightforward to be causing the quantum bug. However, I suspect your problem is with using Net::LDAP asynchronously. Try setting "async" to zero - your ldap object may not be completely finished with everything it is attempting to do before you ask it to do something else. This is just a guess, mind you...
      Yes, I tried standard debugging techniques. The LDAP bind() and search() are where it fails.

      An example of how random it is(with Net::LDAP debugging off):

      emeitner@brule:~/work/perl-ldap$ while : ; do ./simple.pl ; sleep 1; d +one bind(): I/O Error Resource temporarily unavailable bind(): I/O Error Resource temporarily unavailable bind(): I/O Error Resource temporarily unavailable search(): I/O Error Resource temporarily unavailable bind(): I/O Error Resource temporarily unavailable bind(): I/O Error Resource temporarily unavailable search(): I/O Error Resource temporarily unavailable bind(): I/O Error Resource temporarily unavailable bind(): I/O Error Resource temporarily unavailable search(): I/O Error Resource temporarily unavailable bind(): I/O Error Resource temporarily unavailable search(): I/O Error Resource temporarily unavailable

      I DID notice during my investigation that if I use other modules such as Data::Dumper the script will actually work once out of every 20 runs or so.

      Yep, I tried that too. It behaves the same in either sync or async modes.
        Ok... Try putting an explicit $ldap->sync() before your bind() and search() calls.