2011-07-27 9 views
8

guión Un Perl (que utiliza una carga de módulos localmente escritos, y está en desarrollo activo) acaba de comenzar la producción esporádicaCómo investigar "intento de liberar a escalar sin referencias"

"intento de liberar a escalar sin referencias: SV 0xa6e685c, intérprete de Perl: 0x96d9008 durante la destrucción global. "

mensajes. Esto siempre es repetible, en el sentido de que una secuencia particular de comandos siempre produce el mensaje si alguna vez lo hace, pero no he logrado aislar un caso simple o independiente que lo provoque. En particular, todavía no lo he visto cuando ejecuto el script desde el depurador Perl (puedo obtenerlo al depurar un script que usa IPC :: Open3 para ejecutar mi script de destino).

Me doy cuenta de que esto es solo posiblemente un error en Perl, pero es mucho más probable que sea algo que estoy haciendo, muy probablemente en mis llamadas a SVN :: Client; pero estoy perplejo por una forma de investigarlo, y me pregunté si alguien tenía alguna indicación.

Perl 5.10.0; Varias versiones de Fedora Linux. Voy a probarlo en Perl 5.12, pero a menos que se manifieste allí también, realmente no me ayudará. Editar: un caso particular que da confiablemente el mensaje en 5.10 no en 5.12. Lamentablemente, eso realmente no me dice nada.

+2

5,14 es la versión actual de Perl. 5.12 y 5.10 son bastante viejos. Pero de todos modos, compila perl con depuración para que puedas ver lo que creó el SV en 0xa6e685c. Esto debería apuntarle en la dirección correcta. (Mi suposición es que SVN :: Client u otro módulo XS está roto.) – jrockway

Respuesta

1

Esto a menudo se asocia con problemas de subprocesamiento, específicamente al pasar una variable de un subproceso a una subrutina que se ejecuta en otro. He aquí un ejemplo abstracto del patrón:

A.pl

.... 
my $dummy; 
threads->create("B::c", ($dummy)); 
.... 

B.pm

.... 
sub c{...} 
.... 

Soy consciente de que la búsqueda de algo que se parece a esto en su "carga de los módulos escritos localmente "no serán fáciles. Tal vez pueda cortar trozos de su programa hasta que encuentre algo que haga una diferencia en el comportamiento; eso debería ayudarte a aislar el problema.

+0

Debería dar un enlace a la publicación original (también lo encontré en google). – TLP

+0

Esto no es solo un reenvío, pero sí, el código de muestra y la idea básica se tomaron de http://www.tek-tips.com/viewthread.cfm?qid=1346880&page=133. Confirmé la idea en varios otros enlaces antes de redactar esta respuesta. Debería haber dado crédito para empezar. –

+0

Estoy 99.9% seguro de que no usamos hilos en nuestro código. Tal vez un módulo estándar o CPAN. Gracias de cualquier manera. –

1

También encuentro estos mensajes mucho (en código que usa mucho fork) y el problema relacionado de fallas de segmentación durante la fase de destrucción global (es decir, el programa puede completarse normalmente, pero puede ocurrir un error durante la destrucción global hacer que el programa salga con un código de salida distinto de cero). Tampoco sé si estos problemas pueden solucionarse, pero generalmente se pueden solucionar.

En primer lugar, utilizar una variable global para detectar si se encuentra en la fase de destrucción global:

our $_GLOBAL_DESTRUCTION = 0; 
END { $_GLOBAL_DESTRUCTION = 1; } 

(véase también la ${^GLOBAL_PHASE} variable disponible en Perl v> = 5.13.7)

Entonces evitar ejecutar el código problemático durante la fase de destrucción global:

sub MyObject::DESTROY { 
    return if $_GLOBAL_DESTRUCTION; 
    ... # else proceed 
} 

sub other_function_that_frees_unreferenced_scalars { 
    return if $_GLOBAL_DESTRUCTION; 
    ... 
} 
+2

A veces es necesario omitir la destrucción global, pero si está utilizando módulos XS que no pueden sobrevivir a fork + destroy, deben corregirse. Si el código de Perl puro está haciendo esto, ¡presente un informe de errores Perl! – jrockway

+3

La situación específica que tengo en mente es un controlador SIGCHLD que actualiza un montón de estado cuando se cosecha un proceso secundario. Supongamos ahora que el programa principal finaliza y, en medio de la destrucción global, finaliza un proceso hijo anterior y se llama al controlador SIGCHLD. No tiene sentido actualizar nada porque el programa principal ha terminado, y la mitad de las cosas que estarías actualizando ha sido basura (pero solo la mitad). Entonces le dice a su manejador de señal que no necesita hacer nada una vez que la cola END ha comenzado. – mob

+0

Gracias por la sugerencia, pero no sé lo que es "el código problemático". Creo que es muy probable que esté en los enlaces de Subversion, sobre los cuales no tengo control. La pregunta es si es solo un error en ellos, o si es el resultado de una llamada dudosa que estoy haciendo. –

2

respuesta tardía, pero me escribió un largo artículo sobre este tema en particular que shou ld ayuda con la depuración: The Dreaded "Attempt to free unreferenced scalar".

+0

Si bien esto podría responder teóricamente a la pregunta, [sería preferible] (http://meta.stackexchange.com/q/8259) incluir aquí las partes esenciales de la respuesta y proporcionar el enlace de referencia. – Hasturkun

0

Busque cualquier tipoglobos que hagan referencia a punteros, p. un typeglob para un hash de hashes. Me encontré con esto con un typeglob utilizado para cambiar entre diferentes hashes de matrices.El error surgió cuando las entradas se eliminaron utilizando tanto el typeglob como el hash original. Usar un hash simple sin anidar o deshacerse del typeglob eliminó el problema.

0

foreach (@var) es otro buen candidato para la inspección.

El siguiente código me dio esta advertencia:

foreach (@list1) { 
    my ($i, $j) = @$_; 
    my $k = get_k($i, $j); 
    foreach (@$k) { 
     sub_that_uses_fork($_); 
    } 
} 

pero el siguiente no lo hicieron:

while (scalar(@list1)) { 
    my ($i, $j) = @{shift(@list1)}; 
    my $k = get_k($i, $j); 
    foreach (@$k) { 
     sub_that_uses_fork($_); 
    } 
} 
Cuestiones relacionadas