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

Hi, My longtime working project, with sockets in threads, became unstable. After unistalling Activestate Perl 5.8.0 and FRESH installing v5.8.2 b808 (Windows msi installer) built for MSWin32-x86-multi-thread. I get many Perl errors such as "Attempt to free unreferenced scalar: SV 0x280bac00 at D:/Perl/lib/IO/Socket.pm line 46." and similar others. Also, Perl.exe crashs! easily :( This simple code will produce the error and/or crash Perl.exe. Using Activestate Perl 5.8.2 on Windows 2000 Server SP2. It worked just fine for me on v5.8.0. You may need to retry few times to get the error or the crash. Please advise :) ==============================
#!/usr/bin/perl use 5.008; # 5.8 required for "stable" threading use strict; use warnings; use threads; use threads::shared; use IO::SOCKET; for (my $i = 0; $i < 5; $i++) { threads->create(\&start_thread, "www.yahoo.com:80")->detach; # threads->create(\&start_thread, "www.yahoo.com:80")->join; #wor +ks, but who cares :) } sleep(5); print STDERR "done\n"; exit; sub start_thread { my $hostport = shift; my $tid = threads->self->tid; print STDERR "Connecting $tid\n"; my $socket = IO::Socket::INET->new(Proto => "tcp", PeerAddr => $hostport); $socket or die "[$!]\n"; $socket->autoflush(1); close($socket); print STDERR "Closing $tid\n"; }

Replies are listed 'Best First'.
Re: Activestate 5.8.2 broke my threads :(
by Roger (Parson) on Dec 22, 2003 at 05:50 UTC
    I suspect it has to do with the threads object's lexical scoping and perl's garbage collector. I modified your code to below and it works -
    #!/usr/bin/perl use 5.008; # 5.8 required for "stable" threading use strict; use warnings; use threads; use threads::shared; use IO::SOCKET; use Data::Dumper; my @threads; for (my $i = 0; $i < 5; $i++) { my $thread = threads->create(\&start_thread, "localhost:80"); $thread->detach; push @threads, $thread; } sleep(2); print STDERR "done\n"; exit; sub start_thread { my $tid = threads->self->tid; print STDERR "Start $tid\n"; sleep(1); # do something in the thread print STDERR "Finish $tid\n"; }
    What I think is happenning is that threads->create creates a temporary object (in threads module, create is new), and this object goes out of scope at the end of the for block and Perl happily 'freed' it with the garbage collector. You have to make sure that the created threads object does not go out of scope to have it working properly.

      Roger, your explanation might have hit the bug behind it. (I don't comment, as it is speculation any way. We all know that they fixed lots of thread-related memory leaks in 5.8.2, at least according to the document. It is not a surprise that they might had some of the bugs over killed, and now free the same piece allocated memory twice. Not neccessary to be garbage collector related ;-)

      However this is not a fix, but rather a workaround, as the OP's code should be just fine, without the array you added. A Perl bug is still a Perl bug, and there is no point for application programmer to suffer from it, and worry about workaround.

      Roger, Thanks for your effort, much appreciated, especially that as side effect fixed my problem :), which I now consider real Perl 5.8.2 bug, at least for AS Windows. But one word first. My problem was also to do with sockets in concurrent threads, so replacing in the thread the socket code with sleep() is not true simulation of the problem. So I want to report the fix for the record: What fixes the problem is moving the threads->detach() on separate line! Thats all. (Long time ago I used to have the lines separate, but some Perl Guru told me it is not Perlish :(, but it worked until 5.8.2. BTW, I still have some instability problems that were not present in earlier version. Thanks all.
        I have considered moving threads->detach() on a separate line before I made my original post though, but moving detach on to another line is not doing what you think it's doing. The following codes are not equivalent:
        threads->create(\&create_threads, "param")->detach();
        and
        threads->create(\&create_threads, "param"); threads->detach();
        In the first example, detach() is performed on the object returned by threads->create(), which detaches the thread created. Moving detach() on a separate line does not detach the thread at all, calling threads->detach() separately has no effect on the thread you just created.

        The proof? Well, there is a threads->list() function that lists all non-joined, non-detached threads. Add threads->list() after threads->detach() showed that the created thread did not get detached at all.

        I agree there is definitely a bug with detach() on out of scope object, but moving detach() on a separate line is not a fix. You must call $thread_created->detach() to truly detach the thread.

Did you report it to ActiveState?
by PodMaster (Abbot) on Dec 22, 2003 at 07:04 UTC
    Did you report it to ActiveState? You should go ahead and do that.

    I have compiled my own win32 ActiveState compatible perl-5.8.2 , and the code runs just fine.

    To see how ActivePerl-5.8.2 differs from per-5.8.2 check out http://downloads.activestate.com/ActivePerl/src/5.8/AP808_diff.txt

    A lot of the edits are completely benign, but some changes I just cannot understand (if they were improving perl, i'm sure the p5p would've accepted patches).

    It's one of the reasons I've stopped installing ActivePerl.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      Most of that diff seems to be post-5.8.2 patches that AS apparently deemed benign enough to include. Were there particular changes that you questioned?
        That is what I question (post release patches AS deemed benign enough to include). It's not the first time that AS in their "quest" to improve their release has introduced bugs (like in this case), that would've been worked out in the normal release cycle.

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

      It's one of the reasons I've stopped installing ActivePerl.
      You've quit using AS - what are some of the other reasons?

      Do you build your own perl or do you use another build (ie Apache's build)?

        Like I said, I compile my own. The so called "Apache's" build is just ActivePerl.

        Some other reasons i've stopped using AS include actions such as purposely removing pod from their modules, for example ActivePerl::DocTools (inspired me to write Pod::Master), among others. I don't know why they did that, I just know I don't like it :)

        Another reason is the "ActiveState Community License". Perl is released under the Artistic License or the GNU General Public License. I'm no expert, but whatever they were trying to accomplish with their "community license" does not look right to me, and I just don't like it (for one thing, if you type `perl -V', it makes no mention of their community license).

        That's pretty much it, well, that's what I can remember (*mumble* various bugs with PPM...and PerlScript security issues... don't ask me).

        Another reasons is that since I got a compiler I got kind of compile-happy .. I started smoking perl... this weighed heavily on my decision not to use ActivePerl.

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Activestate 5.8.2 broke my threads :(
by pg (Canon) on Dec 22, 2003 at 05:51 UTC

    I don't have 5.8.2 installed, so cannot repeat your problem, but I want to point out this line, so it does not confuse thread newbies:

    #threads->create(\&start_thread, "www.yahoo.com:80")->join; #works, bu +t who cares :)

    For anyone wish to handle different sites multi-threaded, this code does not work for you, as it is not really multi-threaded in the way you want. You have to call detach() or simply don't call anything. By calling join(), the loop will halt until the child thread completes and returns.

    I am not saying the author of the original post does not understand this, as he might just want to use join() to contrast the detach(), but a better contrast is:

    threads->create(\&start_thread, "www.yahoo.com:80");

      PG, I thought I was clear to give in-line COMMENTED EXAMPLE, to SHOW that it is the CONCURRENCY that is broken. I guess writing a comment on the commented line of the join "this works but who cares :)" was confusing to some. Sorry. But do you have a real answer too? Do you need more info? Did you try it on some 5.8.2 to check? Maybe on Windows? Maybe the newbies that you try to teach want to know why one program works just fine on 5.8.0 but blows Perl.exe on 5.8.2?