2010-07-20 13 views
9

Sto provando a prendere un programma Perl che ho scritto e infilato. Il problema è che ho letto che alcuni moduli non sono "thread safe". Come faccio a sapere se un modulo è thread-safe? Ho cercato un elenco e non riesco a individuarne uno.Moduli Safe Thread Perl

per testare un modulo che uso di frequente (Testo :: CSV_XS) Ho provato il seguente codice out:

use strict; 
use warnings; 
use threads; 
use threads::shared; 
require Text::CSV_XS; 

my $CSV = Text::CSV_XS->new ({ binary => 1, eol => "\n" }) or die("Cannot use CSV: ".Text::CSV->error_diag()); 
open my $OUTPUT , ">:encoding(utf8)", "test.csv" or die("test.csv: $!"); 

share($CSV); 

my $thr1 = threads->create(\&sayHello('1')); 
my $thr2 = threads->create(\&sayHello('2')); 
my $thr3 = threads->create(\&sayHello('3')); 


sub sayHello 
{ 
my($num) = @_; 

print("Hello thread number: $num\n"); 

my @row = ($num); 
    lock($CSV);{ 
    $CSV->print($OUTPUT, \@row); 
    $OUTPUT->autoflush(1); 
    }#lock 
}#sayHello 

L'uscita ricevo è il seguente:

 
Hello thread number: 1 
Segmentation fault 

significa il modulo non è thread-safe o è un altro problema?

Grazie

+1

Provate a venire con il programma più piccolo è possibile che provoca l'errore di segmentazione. – mob

risposta

32

In generale, moduli di base e di alta visibilità sono thread-safe a meno che la loro documentazione dice il contrario.

Detto questo, ci sono un paio di passi falsi nel tuo post:

  1. share($CSV)
    questo cancella $CSV (un rifhash benedetto), just as documented in threads. In generale, si desidera condividere() oggetti complessi precedenti a all'inizializzazione o, in questo caso, condividere() una qualche stupida variabile $lock tra i thread.
    Poiché $CSV contiene lo stato per l'XS sottostante, ciò potrebbe comportare un comportamento non definito.

    Ma questo non è il tuo segfault.

  2. threads->create(\&sayHello('1'));
    Hai erroneamente invocando sayHello(1) nel thread principale e passando un riferimento al suo valore di ritorno a threads->create() come (fasullo) inizio di routine. Lei abbia voluto dire:

    threads->create(\&sayHello, '1'); 
    

    Ma questo non è il tuo segmentation fault.

    (EDIT tanto per chiarire - una routine di avvio male qui non rischia un SEGV in ogni caso threads::create lamenta correttamente se il nome di subroutine non riconosciuto o non-CODE ref viene passato in Nel tuo caso,.. tuttavia, si esegue la segfault troppo rapidamente per raggiungere questa gestione degli errori.)

  3. Le codifiche non sono thread-safe.
    Ancora as documented in encodings, il modulo encoding non è thread-safe. Ecco il codice più piccolo possibile, ho potuto ottenere di riprodurre i sintomi:

    use threads; 
    open my $OUTPUT , ">:encoding(utf8)", "/dev/null" or die $!; 
    threads->create(sub {})->join; 
    

    Ecco Perl 5.12.1 con fili-1,77 su i686-linux-thread-multi, se siete interessati. Lascia cadere la magia "utf8" e funziona perfettamente.

    questa è la tua segfault

+0

bella risposta ... – masonk

+0

Questo mi ha risparmiato ore di ricerca della causa del mio segfault. Grazie! –