bug-wget
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-wget] --connect-timeout doesn't work on Windows


From: Eli Zaretskii
Subject: Re: [Bug-wget] --connect-timeout doesn't work on Windows
Date: Tue, 17 Mar 2015 17:27:14 +0200

> Date: Sat, 14 Mar 2015 21:18:26 +0100
> From: Gisle Vanem <address@hidden>
> 
> I see the from the call-stack that connect() is hanging inside
> Gnulib:
>    ...
>    ntdll.dll!ZwWaitForSingleObject+0xc
>    ntdll.dll!RtlInterlockedPushEntrySList+0x32b
>    ntdll.dll!RtlInterlockedPushEntrySList+0x355
>    ntdll.dll!RtlResetNtUserPfn+0x3f
>    wget.exe!close_fd_maybe_socket+0x36
>    wget.exe!execute_close_hooks+0x30
>    wget.exe!execute_all_close_hooks+0x17
>    wget.exe!rpl_close+0x12
>    wget.exe!connect_to_host+0x3ea
>    wget.exe!gethttp+0x686
>    wget.exe!http_loop+0x430
>    wget.exe!retrieve_url+0x1cb
>    ..
> 
> And from the command 'wget -d --connect-timeout=4 http://192.0.2.1:12345/' + 
> ^C:
> 
>    Setting --connect-timeout (connecttimeout) to 4
>    DEBUG output created by Wget 1.15.00 (09-March-2015) on Win-8.1. Build 
> 9600 (MSVC).
>    ...
>    seconds 0.00, Connecting to 192.0.2.1:12345... seconds 4.00,
> 
> So it seems the 'run_with_timeout()' used to connect works fine since
> the thread is not running. So it seems the Gnulib's close() is blocking
> for an unknown reason.

Attaching a debugger shows that it hangs inside the call to
WSAEnumNetworkEvents, here:

  /* Test whether fd refers to a socket.  */
  sock = FD_TO_SOCKET (fd);
  ev.lNetworkEvents = 0xDEADBEEF;
  WSAEnumNetworkEvents (sock, NULL, &ev); <<<<<<<<<<<<<<<<<<<<<<<
  if (ev.lNetworkEvents != 0xDEADBEEF)
    {
      /* fd refers to a socket.  */
      /* FIXME: other applications, like squid, use an undocumented
         _free_osfhnd free function.  But this is not enough: The 'osfile'
         flags for fd also needs to be cleared, but it is hard to access it.
         Instead, here we just close twice the file descriptor.  */
      if (closesocket (sock))

This is Gnulib trying to establish that the file descriptor refers to
a socket.  WSAEnumNetworkEvents waits forever, I think because we
never succeeded to connect, and perhaps also because the socket is
blocking.

The following simple kludge works around the problem for me:

--- src/connect.c~0     2014-12-02 09:49:37.000000000 +0200
+++ src/connect.c       2015-03-17 17:14:48.414375000 +0200
@@ -364,7 +364,12 @@ connect_to_ip (const ip_address *ip, int
        logprintf.  */
     int save_errno = errno;
     if (sock >= 0)
-      fd_close (sock);
+      {
+#ifdef WIN32
+       if (errno != ETIMEDOUT)
+#endif
+         fd_close (sock);
+      }
     if (print)
       logprintf (LOG_VERBOSE, _("failed: %s.\n"), strerror (errno));
     errno = save_errno;

After applying this, I get the expected results:

  wget --connect-timeout=1 -t 3 http://192.0.2.1:12345/
  --2015-03-17 17:18:07--  http://192.0.2.1:12345/
  Connecting to 192.0.2.1:12345... failed: Connection timed out.
  Retrying.

  --2015-03-17 17:18:09--  (try: 2)  http://192.0.2.1:12345/
  Connecting to 192.0.2.1:12345... failed: Connection timed out.
  Retrying.

  --2015-03-17 17:18:12--  (try: 3)  http://192.0.2.1:12345/
  Connecting to 192.0.2.1:12345... failed: Connection timed out.
  Giving up.

If there's a more elegant way of fixing this, I'm all ears.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]