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

Hi,

Is there documentation somewhere that would explain what needs to be done to make (eg) Math::GMP threadsafe ?

My (implicit) assertion that Math::GMP is not threadsafe is based on the fact that the following script segfaults when run on a threaded build of perl (and where Math::GMP itself has been built against a libgmp that is reentrant and threadsafe):
use threads; use warnings; use Math::GMP; $th1 = threads->new(\&start_thread1, '123' x 11); $ret1 = $th1->join(); if(ref($ret1) eq 'Math::GMP') { print "\$ret1 => ", ref($ret1), " ", Math::GMP::get_str_gmp($ret1, 1 +0), "\n"; } sub start_thread1 { my $mbi = Math::GMP->new($_[0]); return $mbi; }
I'm seeking information that doesn't pre-suppose that the reader is threads-savvy. Just a simple "how to" (if such exists) would be best .... anything more detailed would quite likely be lost on me :-)

I have another question: Is Math::BigInt threadsafe ? On the basis that the following script outputs the expected value, I'm thinking the answer could well be "yes":
use threads; use warnings; #use Math::Pari; use Math::BigInt; $th1 = threads->new(\&start_thread1, '123' x 11); $ret1 = $th1->join(); print $ret1, "\n"; sub start_thread1 { my $mbi = Math::BigInt->new($_[0]); return $mbi; } __END__ Outputs: 123123123123123123123123123123123
But then - if I so much as load Math::Pari then that script, too, segfaults. Does that indicate that Math::BigInt is *not* threadsafe ? Or does it merely indicate that one ought not to load Math::Pari in a script that invloves threading ?

Cheers,
Rob

Replies are listed 'Best First'.
Re: Writing threadsafe perl extensions
by BrowserUk (Patriarch) on Oct 21, 2007 at 12:40 UTC

    As with most of these 'non-threadsafe' problems, it is the near useless process of implicit cloning, that is at fault. If you avoid it, and manually load the code into the thread where it is used, it works fine:

    #! perl -slw use strict; use threads; sub t { require Math::Pari; eval { use Math::BigInt; }; my $mbi = Math::BigInt->new( $_[ 0 ] ); $mbi /= 11; return $mbi; } print threads->create( \&t, '123' x 11 )->join; __END__ c:\test>t-pari 11193011193011193011193011193011

    Using Math::BigInt without Math::Pari in multiple threads this way also works:

    #! perl -slw use strict; use threads; sub t { # require Math::Pari; eval { use Math::BigInt; }; my $mbi = Math::BigInt->new( $_[ 0 ] ); $mbi /= 11; return $mbi; } print threads->create( \&t, '123' x 11 )->join; print threads->create( \&t, '123' x 21 )->join; __END__ c:\test>t-pari 11193011193011193011193011193011 11193011193011193011193011193011193011193011193011193011193011

    But with Math::Pari it does not. This code hangs:

    #! perl -slw use strict; use threads; sub t { require Math::Pari; eval { use Math::BigInt; }; my $mbi = Math::BigInt->new( $_[ 0 ] ); $mbi /= 11; return $mbi; } print threads->create( \&t, '123' x 11 )->join; print threads->create( \&t, '123' x 21 )->join; __END__ c:\test>t-pari 11193011193011193011193011193011 Terminating on signal SIGINT(2)

    Which seems to put the problem within Math::Pari. The following from the Math Pari POD may give some indication to the cause:

    Legacy implementations of dynalinking require the code of DLL to be compiled to be "position independent" code (PIC). This slows down the execution, while allowing sharing the loaded copy of the DLL between different processes. On contemeporary architectures the same effect is allowed without the position-independent hack.

    Currently, PARI assembler files are not position-independent. When compiled for the dynamic linking on legacy systems, this creates a DLL which cannot be shared between processes. Some legacy systems are reported to recognize this situation, and load the DLL as a non-shared module. However, there may be systems (are there?) on which this can cause some "problems".

    Summary: if the dynaloading on your system requires some kind of C<-fPIC> flag, using "assembler" compiles (anything but C<machine=none>) *may* force you to do a static build (i.e., creation of a custom Perl executable with

    perl Makefile.PL static make perl make test_static
    ).

    I don't have Math::GMP, so I haven't checked whether any of hthis translates to that module.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I don't have Math::GMP, so I haven't checked whether any of this translates to that module

      Pity ... that's the one I'm most interested in :-)
      Given that the following script works fine:
      #!perl -slw use Math::GMP; my $ret = Math::GMP->new('123' x 11); print Math::GMP::get_str_gmp($ret, 10); __END__ C:\_32\pscrpt\threads>perl gmp2.pl 123123123123123123123123123123123
      if Math::GMP were threadsafe, would you expect that the following also outputs the same:
      #!perl -slw use threads; use Math::GMP; sub t1 { my $mbi = Math::GMP->new($_[0]); return $mbi; } my $th1 = threads->new(\&t1, '123' x 11); my $ret1 = $th1->join; print Math::GMP::get_str_gmp($ret1, 10);
      (It doesn't - it just segfaults.) Does that therefore prove that Math::GMP is not threadsafe ? - or is there yet a possible rendition that may prove fruitful ?

      Cheers,
      Rob

        What happens with this?

        #!perl -slw use threads; sub t1 { eval{ use Math::GMP }; my $mbi = Math::GMP->new($_[0]); return $mbi; } my $th1 = threads->new(\&t1, '123' x 11); my $ret1 = $th1->join; print Math::GMP::get_str_gmp($ret1, 10);

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Writing threadsafe perl extensions
by shmem (Chancellor) on Oct 21, 2007 at 08:37 UTC
    Running under gdb:
    qwurx [shmem] ~ > gdb perl ... (legal mumbo) ... (gdb) run pari-threaded.pl Starting program: /usr/bin/perl pari-threaded.pl (no debugging symbols found) ... Program received signal SIGSEGV, Segmentation fault. [Switching to Thread -1209108800 (LWP 31332)] 0x007046cc in moveoffstack_newer_than () from /usr/lib/perl5/site_perl +/5.8.8/i386-linux-thread-multi/auto/Math/Pari/Pari.so (gdb)

    Conclusion: Math::Pari is not thread-safe.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Writing threadsafe perl extensions
by lorn (Monk) on Oct 22, 2007 at 15:03 UTC

    Well, the answers above said "Math::*" its not thread safe, i recommend that to try POE, i did not test with "Math::*" but, works for me when i need a thread script ;)