2008-11-26 15 views
12

Tengo algo de código Perl que funciona muy bien fuera del depurador:¿Por qué este bloque Perl BEGIN actúa de forma diferente en el depurador?

% perl somefile.pl 

pero cuando lo ejecuto en el interior del depurador:

% perl -d somefile.pl 

se comporta de manera diferente.

Los archivos en cuestión (hay varios) son parte del conjunto de pruebas para un gran módulo Perl (~ 20K líneas de código). Las pruebas realizan una gran cantidad de trabajo de configuración en tiempo de compilación y usan bloques BEGIN. Aquí hay un código mínimos para la reproducción:

BEGIN 
{ 
    package MyEx; 

    sub new { bless {}, shift } 

    package main; 

    eval { die MyEx->new }; 

    if([email protected]) 
    { 
    die "Really die" unless([email protected]>isa('MyEx')); 
    } 
} 

print "OK\n"; 

Si pones eso en somefile.pl y ejecutarlo, se imprime "OK" como se esperaba. Si lo ejecuta en el depurador con perl -d somefile.pl, se muere con este error:

Can't call method "isa" without a package or object reference ... 

El resultado es que [email protected] no es un objeto cuando el código se ejecuta en el depurador. En cambio, es un escalar no bendito que contiene esta cadena:

" at somefile.pl line 9 
    eval {...} called at somefile.pl line 9 
    main::BEGIN() called at somefile.pl line 16 
    eval {...} called at somefile.pl line 16 
" 

(nuevas líneas internas y espacios preservados Ese es el texto literal, incluso los "..." s.).

necesito código como este para funcionar en el depurador Usar el depurador en el banco de pruebas es una parte importante de mi flujo de trabajo. El módulo usa objetos de excepción y hace muchas cosas en el tiempo de compilación y espera que un objeto sea lanzado al ser capturado.

Mi pregunta (finalmente) es esta: ¿Cómo puedo hacer que esto funcione? ¿Hay alguna solución? ¿Es esto un error en el módulo de depuración de Perl? ¿Cuál es la mejor manera de resolver esto? (Sé que son varias preguntas, pero todas están relacionadas).

Estoy usando Perl 5.10.0 en Mac OS X 10.5.5.


Lo dieLevel sugerido por Adam Bellaire parecía prometedor, y de hecho algo (no se puede averiguar qué) está fijando a 1 para mí. Pero lo configuré en 0 usando un archivo ~/.perldb y el problema persiste. De hecho, me puse los tres de los ajustes relacionados a 0. Mi ~/.perldb archivo:

parse_options('dieLevel=0 warnLevel=0 signalLevel=0'); 

me confirmaron que los ajustes son, en efecto, mediante la ejecución del comando o en el depurador. Los veo todos configurados en 0 cuando ejecuto perl -de 0 y también cuando ejecuto el archivo somefile.pl real.


Gracias, brian. Usé perlbug para presentar un error (RT 60890) y comencé a rociar local $SIG{'__DIE__'} en todos los lugares apropiados de mi código. (Me di cuenta en el fallo que perldoc perldebug todavía parece dar a entender que el valor por defecto es 0. dieLevel)

Respuesta

14

Este es un problema con perl5db.pl que crea __DIE__ controladores. Si localicé $SIG{__DIE__} en su eval, las cosas funcionan como esperaba.

 
eval { 
    local $SIG{__DIE__}; 
    die MyEx->new 
    }; 

Si no lo hace, usted está recibiendo el manejador de base de datos :: dbdie, que utiliza la carpa :: longmess. Eso no debería suceder si dieLevel es 0, pero de manera predeterminada es 1 y se establece en 1 si no está definido. Este fue un parche para perl5db.pl en 2001, y anteriormente el defecto había sido 0.

Se supone que desactivar esta opción con:

PERLDB_OPT="dieLevel=0" perl5.10.0 -d program 

Pero todavía hay un código de referencia en $SIG{__DIE__} después de eso, y es una referencia a dbdie. Creo que esto es un error al manejar la variable global $prevdie en el dieLevel de perl5db.pl. Al final de dicha subrutina, hay:

 
# perl5db.pl dieLevel, around line 7777 
     elsif ($prevdie) { 
      $SIG{__DIE__} = $prevdie; 
      print $OUT "Default die handler restored.\n"; 
     } 

notar que después de restaurar $SIG{__DIE__}, se mantiene el valor anterior de $prevdie, es decir, lo que está en allí filtraciones a otra llamada. Cuando ejecuto esa línea de comando, hay dos llamadas a dieLevel antes de que maneje PERLDB_OPT, por lo que $prevdie probablemente esté sucio.

Así que, eso es lo que tengo antes, ya no quería pensar en perl5db.pl.

+1

Eres un hombre más valiente que yo, Brian. Cada vez que pienso en hurgar en perl5db, llego a los comentarios sobre lo enredado que es perder mi motivación. –

3

¿Es posible que usted tiene un archivo RC o variable de entorno (PERLDB_OPTS) que está modificando la opción dieLevel del depurador?Personalmente no he usado dieLevel, pero aparentemente cuando se establece en un valor mayor que cero puede forzar el desenrollado de la pila y "tiende a destruir irremediablemente cualquier programa que tome en serio su manejo de excepciones". (Quote from here).

+0

No hay valores env con PERL en ellos, pero parece que mi dieLevel está configurado en 1. ¿Qué podría estar haciendo eso? –

+0

Hmm, el archivo rc se encuentra en ./.perldb o ~/.perldb en sistemas Unix, creo que OS X probablemente usaría el mismo archivo. Por lo que dice la documentación, la opción debe establecerse allí si no está en la línea de comando o en el env. ¿Tal vez puedas intentar establecer explícitamente dieLevel en cero? –

5

Lo considero un error cualquier código de tiempo se comporta de manera diferente en el depurador.

Su problema might tenga relación con esto: Debugger corrupts symbol table munging. Esencialmente, el depurador parece jugar algunos trucos con local, presumiblemente como parte de elementos de sandboxing para proporcionar interactividad. Obviamente, jugar con la tabla de símbolos puede tener efectos secundarios inesperados. Supongo que el depurador está localizando [email protected] y oscureciendo así su objeto. No puedo pensar en una solución alternativa.

+0

¿Quiere decir que lo considera un error en el depurador? –

Cuestiones relacionadas