in reply to threads + sockets stalling question

I'm guessing there's a lock preventing something from being cloned at thread creation.

  • Comment on Re: threads + sockets stalling question

Replies are listed 'Best First'.
Re^2: threads + sockets stalling question
by BrowserUk (Patriarch) on Mar 16, 2010 at 14:54 UTC

    You're right! I tracked as far as entering the perl_clone() call in threads.xs. It goes in and doesn't come out until I connect to the socket from an external process:

    C:\test>828831.pl paused # threads.xs(695) # threads.xs(700) # threads.xs(722) # threads.xs(736) # threads.xs(765) # threads.xs(774) # threads.xs(788) # threads.xs(796) # threads.xs(824) # threads.xs(834) # threads.xs(904) # threads.xs(906) # threads.xs(929) accept loop started paused # threads.xs(695) # threads.xs(700) # threads.xs(722) # threads.xs(736) # threads.xs(765) ### hangs here until Connect from IO::Socket::INET=GLOB(0x544e2a0) ### I connect with tel +net # threads.xs(774) ### then everything r +uns on # threads.xs(788) # threads.xs(796) # threads.xs(824) # threads.xs(834) # threads.xs(904) # threads.xs(906) # threads.xs(929) Client 1 started ### and the internal c +lients connect

    So the question becomes, what could perl_clone() be locking and not freeing, that gets freed when accept() gets a connection from an external process?


    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^2: threads + sockets stalling question
by BrowserUk (Patriarch) on Mar 17, 2010 at 14:38 UTC

    Hm. The problem comes down to the fact that PerlIO calls the crt fstat() in order to determine if the file descriptor it is trying to clone, is attached to a "regular file".

    As the file descriptor in question is currently in an accept state in another thread and the CRT serialises access, the fstat blocks. The entire Perl_clone() blocks, and the client threads are never started.

    When I connect to the listener from an external process, the accept completes, which unlocks the file descriptor. Thus the fstat() returns allowing the Perl_clone to complete and the client threads get created.

    The real problem here seems to be the hookey methods used inside PerlIO. There has to be a better way than to try to fstat() a socket, to determine if it is socket.


    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.

      Comments in win32sck.c led me to GetFileType(), which might be all that's needed, at least to find out whether a file handle might be a socket.

      As the code is Win32-specific, and Windows 9x isn't supported anymore, this call could maybe used instead of fstat.

        That's a good idea. Unfortunately, I think that the problems go much deeper than I've yet discovered.

        If you stop the code from calling fstat(), it runs on a bit further before hanging again. This time it calls the CRT ftell() on a socket, which blocks because of the lock applied in the accept call. And if you fix that ....

        I tried (more in hope than expectation), that compiling without USE_PERLIO and/or enabling USE_PERLCRT might avoid some of the show stoppers in PERLIO, but it seems that Perl has become dependant upon PerlIO now :(


        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.