Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re: threads->create() blocks on Windows

by BrowserUk (Pope)
on Mar 17, 2014 at 20:21 UTC ( #1078674=note: print w/ replies, xml ) Need Help??


in reply to threads->create() blocks on Windows

Your first thread puts the socket into a blocking read state.

When you attempt to start the second thread, Perl tries to clone $s for that thread, because it closes over $s.

But, the underlying system handle for the socket is locked (by the OS) because the socket is in a blocking read; thus the attempt to clone the handle is blocked until the read completes; which it never will.

As the clone is blocked, the second thread is never started; so no GET is issued, so no reply will be received.

The solution (maybe, depending upon the rest of your application,) it to ensure the get occurs before the read state is entered.

Something like this:

use strict; use warnings; use threads; use IO::Socket::INET; $|++; my $s = IO::Socket::INET->new(PeerAddr => 'www.google.com', PeerPort => 80, Proto => 'tcp') or die "error: $@"; print "create t2\n"; my $t2 = threads->create(sub { # problem: this is never printed print "in t2\n"; $s->send("GET / HTTP/1.1\r\n\r\n"); }, 0 ); # give t1 a moment to execute and to block in the recv call print "sleep 1s\n"; sleep(1); print "sleep done\n"; print "create t1\n"; my $t1 = threads->create(sub { my ($r) = @_; my $data = ''; print "in t1\n"; while( 1 ) { $r->recv($data, 64); print ">>> $data"; } }, $s); # problem: this is never printed, as threads->create never returns print "done\n"; $t1->join(); $t2->join();

Outputs:

C:\test>junk41 create t2 in t2 sleep 1s sleep done create t1 done in t1 >>> HTTP/1.1 302 Found Cache-Control: private Content-Type: text/h>>> tml; charset=UTF-8 Location: http://www.google.co.uk/?gfe_rd=cr>>> &ei=-lgnU7OuDdT88QPQ84 +CwAw Content-Length: 261 Date: Mon, 17 M>>> ar 2014 20:20:10 GMT Server: GFE/2.0 Alternate-Protocol: 80:qu>>> ic <HTML><HEAD><meta http-equiv="content-type" content="text/>>> html;cha +rset=utf-8"> <TITLE>302 Moved</TITLE></HEAD><BODY> <H1>3>>> 02 Moved</H1> The document has moved <A HREF="http://www.google.>>> co.uk/?gfe_rd=cr&amp;ei=-lgnU7OuDdT88QP +Q84CwAw">here</A>. </BOD>>> Y></HTML> Terminating on signal SIGINT(2)

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
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.


Comment on Re: threads->create() blocks on Windows
Select or Download Code
Re^2: threads->create() blocks on Windows
by photron (Novice) on Mar 20, 2014 at 12:35 UTC
    Thanks for the detailed explanation. This seems exactly to be the problem. I cannot create a new thread while another thread does a blocking receive on a global socket. So I'll have to avoid this situation.
Re^2: threads->create() blocks on Windows
by photron (Novice) on Mar 24, 2014 at 17:15 UTC
    But, the underlying system handle for the socket is locked (by the OS) because the socket is in a blocking read; thus the attempt to clone the handle is blocked until the read completes; which it never will.

    Well, this explanation seemed reasonable to me and it seems to indicate that the problem is in Windows itself and that Perl just happens to work in a way that collides with some Windows behavior here if I write my script in a certain way.

    I doubt this now! I had tested this script with Strawberry Perl and Active State Perl and both show the same behavior. But now I tested this with Cygwin's Perl package and it just works. So is this actually a bug in Strawberry and Active State Perl, or is Cygwin just applying some magic here to make this work?

      So is this actually a bug in Strawberry and Active State Perl, or is Cygwin just applying some magic here to make this work?

      Both AS Perl and Strawberry Perl use the MS C-runtime, which is where the internal locking is done. It's not an error, it's a design choice.

      Cygwin on the other hand implements a strictly POSIX-complient C-runtime which makes other choices.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

        Okay, so Cygwin is applying some magic here.

        Anyway, I can reproduce the exact backtrace bulk88 posted and I can only see one thread having a msvcrt.dll frame on its callstack. So I isn't obvious to me why this should be a deadlock with the locks in msvcrt.dll. I looked at the msvcrt.dll code and can see the locking you're talking about. But I can't see how this should be the problem here.

        Also I managed to create another deadlock case in which both threads have no msvcrt.dll frame on their stack, but directly call into ws2_32.dll from the Perl library.

        Anyway, I'll give up on this problem for now and use Cygwin as a workaround.

        Thanks for your help!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1078674]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2014-08-29 21:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (289 votes), past polls