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

This is a really vague question I know, but I have a script in which when IO::Socket (from IO::Socket::INET from HTTP::Deamon) calls getsockname(*), it is blocking, apparently indefinitely.

(*)Corrected name of call thanks to jbert below.

The code is using various "experimental" techniques, so I'm in the lap of the gods for a resolution, so any thoughts as to what might cause this are welcomed, no matter how speculative. This doesn't usually happen, even using threads under Win32 (as this script does), and I'm looking for any clues as to the cause?


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.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

Replies are listed 'Best First'.
Re: getsockaddr() blocks indefinitely? (TFM)
by tye (Sage) on Nov 15, 2007 at 16:10 UTC

    The Win32 SDK says of getsockname() that it can return the following error reason:

    WSAEINPROGRESS
    A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.

    Which implies that the call might hang under those circumstances if the socket is not set to be non-blocking. So set the socket to be non-blocking for that call and you'll probably get that error instead of it hanging (the documentation is not completely clear on that point, as usual).

    - tye        

      tye++. Nail on the head time.

      The client thread is calling getsockname(), meanwhile the main thread has gone back into a blocking accept(). getsockname() won't continue until the accept() completes (another connection comes in).

      Likewise, attempting to set the socket non-blocking (from the thread) won't have an affect until the accept() completes. And setting the listening socket non-blocking before entering the accept() kinda negates the purpose of using threads.

      A (partial at this stage), solution appears to be to change HTTP::Daemon::ClientConn (a part of HTTP::Daemon), so that it calls getsockname() on the client socket, rather than as now, on the parent.

      Eg.

      $uri = $HTTP::URI_CLASS->new($uri, $self->url);

      instead of:

      $uri = $HTTP::URI_CLASS->new($uri, $self->daemon->url);

      which also requires making HTTP::Daemon::ClientConn a subclass of HTTP::Daemon rather than of IO::Socket::INET, in order to resolve the call to method url() which is where the call to getsockname() originates. But that seems to make more sense to me anyway?

      It's still not a complete solution yet, but it does allow thing to progress past the getsockname() call which is progress. It's now completing the get_request() and returning the appropriate information to the caller, but whatever method I then call; send_file(), send_error() etc., none of the output sent by the server ever reaches the client, despite that the prints complete. Time to add some error checking on the prints in HTTP::Daemon I think.


      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: getsockaddr() blocks indefinitely?
by jbert (Priest) on Nov 15, 2007 at 15:50 UTC
    I don't see a getsockaddr, Do you mean getsockname? I can't think of a reason for that to block (should just be a call to get some local state from the kernel).

    But it's not unusual for code to do a gethostbyaddr after calling getsockname, which would do a name resolution (DNS, but perhaps also WINS etc on Windows). This could block for a while (but not indefinitely i think).

    Could it be that? Could you check your name resolution on the box you're on and in particular, can you reverse lookup all your local IPs?

    Can you run a network sniffer and see if your box is generating any lookup traffic (DNS, port 53 - not sure about WINS etc).

      Do you mean getsockname?

      Indeed I do, thanks. I've spent too long staring at the opening line in getsockname which reads Returns the packed sockaddr address of this end of the SOCKET connection, ... trying to work out what that meant!

      I'm trying to trace the call into the perl sources, and the name resolution thing loooks like a likely candidate. Thanks.


      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.