Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ServerSocket.bind should fail fast on Windows #19815

Closed
andersjohnsen opened this issue Jul 3, 2014 · 19 comments
Closed

ServerSocket.bind should fail fast on Windows #19815

andersjohnsen opened this issue Jul 3, 2014 · 19 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io os-windows

Comments

@andersjohnsen
Copy link

From a user:

$ pub --verbose serve
[...]
FINE: Providing sources for analyzer|lib.
FINE: Providing sources for polymer_expressions|lib..
IO : Spawning "cmd /c git --version" in C:[...].
IO : Finished git. Exit code 0.
    | stdout:
    | | git version 1.9.0.msysgit.0
    | Nothing output on stderr.
FINE: Determined git command null.
ERR : OS Error: An invalid argument was supplied.
    | , errno = 10022, address = ::1, port = 42658
FINE: Exception type: SocketException
FINE: e:\b\build\slave\dart-editor-win-dev\build\dart\sdk\lib_internal\pub\lib
src\barback\base_server.dart 46 BaseServer.BaseServer
    | e:\b\build\slave\dart-editor-win-dev\build\dart\sdk\lib_internal\pub\lib
src\barback\barback_server.dart 69 BarbackServer.BarbackServer._
    | e:\b\build\slave\dart-editor-win-dev\build\dart\sdk\lib_internal\pub\lib
src\barback\barback_server.dart 63 BarbackServer.bind.<fn>
    | dart:isolate
                                    _RawReceivePortImpl._handleMessage
    | ===== asynchronous gap ===========================
    | dart:async
[...]

It appears to be failing to bind to an IPv6 address.

I have seen this on two machines so far.

@DartBot
Copy link

DartBot commented Jul 3, 2014

This comment was originally written by da...@grove.cx


Is this a regression from 1.5?

@andersjohnsen
Copy link
Author

Yes, was working in 1.5.

I was able to get further by using

--hostname=127.0.0.1

but then hit issue #19817.

I think it's the case that we do our dual-bind on ipv4/ipv6, but don't gracefully continue if only one of them fails to bind. I have not confirmed this though.

@kasperl
Copy link

kasperl commented Jul 4, 2014

Added this to the 1.6 milestone.
Removed Priority-High label.
Added Priority-Critical label.

@nex3
Copy link
Member

nex3 commented Jul 7, 2014

It looks like http_multi_server isn't properly detecting that IPv6 isn't supported on Windows. However, I think this is a dart:io bug. Here's the code for detecting this:

    /// Returns whether this computer supports binding to IPv6 addresses.
    Future<bool> get supportsIpV6 {
      if (_supportsIpV6 != null) return new Future.value(_supportsIpV6);

      return ServerSocket.bind(InternetAddress.LOOPBACK_IP_V6, 0).then((socket) {
        _supportsIpV6 = true;
        socket.close();
        return true;
      }).catchError((error) {
        if (error is! SocketException) throw error;
        _supportsIpV6 = false;
        return false;
      });
    }

However, in the error you're seeing, it looks like binding to the socket is succeeding, despite IPv6 being unsupported. Instead, it looks like the SocketException is only being thrown when the HTTP stream is listened to. This is confusing and contrary to the behavior on other operating systems.


Removed Area-Pub label.
Added Area-Library, Library-IO labels.
Changed the title to: "ServerSocket.bind should fail fast on Windows".

@dgrove
Copy link
Contributor

dgrove commented Jul 8, 2014

@ajohnsen - are you likely to be able to fix this soon, or should pub work around it?


cc @skabet.

@andersjohnsen
Copy link
Author

So, I looked into this a bit. First, I was completely unable to reproduce this on my machine, as it's impossible to disable the ipv6 loopback interface on Windows 7. I did try to bypass by using other addresses (e.g. binding to "::2"), and did get the error when expected (onError of bind future). To summarize, I'm not able to confirm(nor disprove) an dart:io issue.

That being said, I think the approach for detecting IPv6 here may be problematic. This is detecting the loopback device only. If it was used for later binding to a physical interface address, it could start by passing this test, but then fail when a (wrong) address was given.

I think it should be changed to do the following:

* Call bind for both IPv4 and IPv6 (note that bind may need to take an tuple of 2 addresses).

  • When both are done (success or failure), the overall bind is completed with either success if either is successful, or failure if both fails.
  • Listen on the proxy 'socket' will listen on both (if non failed earlier).
  • Errors will be ignored, unless only one listening socket remains.

That way it will mimic the exact behavior of our normal server sockets, without adding special IPv6 detection. Also, I don't see a need for caching the ipv6 detection. Each address is unique, and may fail on its own terms.


Removed Area-Library, Library-IO labels.
Added Area-Pub label.

@munificent
Copy link
Member

I'm trying to repro this on my Windows box, but I haven't been able to either. I'm on Windows 7. I can't seem to effectively disable IPv6. I've tried both:

http://www.informationweek.com/how-to-disable-ipv6-on-windows-7-/d/d-id/1099490
http://tweaks.com/windows/40099/how-to-properly-disable-ipv6/

Even after doing this, pub serve still binds to the IPv6 loopback, and I can still hit it with [::1]:8080. :(

Anders, I'll talk to Nathan and look into your suggestion, though I won't be able to tell if it actually helps or not.

@munificent
Copy link
Member

Set owner to @munificent.
Added Accepted label.

@munificent
Copy link
Member

Added Started label.

@munificent
Copy link
Member

In-progress patch: https://codereview.chromium.org/375113002/

@sgjesse
Copy link
Contributor

sgjesse commented Jul 9, 2014

First of all do we have a consistent way of testing this? When this first surfaced in issue #11165 I was able to repro it using a personal laptop at home, but that does not fail anymore.

The reason for Windows failing late is that even though the Dart bind call actually does both bind and listen C-call the error does not happen until an accept is issued - probably due to the use of IO completion ports. We don't issue accepts until listen is called in Dart. Maybe we could issue one accept immediately to catch this.

Another option is to change the probing to first try to a basic ServerSocket for IPv6, and actually make a connection. If that works IPv6 should be fine for HTTP as well.

Finally could we just listen on 127.0.0.1? The browser will try all addresses returned from DNS, which on Windows is [::1, 127.0.0.1] for "localhost", and the dart:io client does the same. Are there other tools we use for which this will not work?

@nex3
Copy link
Member

nex3 commented Jul 9, 2014

The reason for Windows failing late is that even though the Dart bind call actually does both bind and listen C-call the error does not happen until an accept is issued - probably due to the use of IO completion ports. We don't issue accepts until listen is called in Dart. Maybe we could issue one accept immediately to catch this.

This would be nice not just for this code, but so [ServerSocket] generally had consistent error behavior across platforms.

Finally could we just listen on 127.0.0.1? The browser will try all addresses returned from DNS, which on Windows is [::1, 127.0.0.1] for "localhost", and the dart:io client does the same. Are there other tools we use for which this will not work?

This is what we were doing before, but it was flaky on OS X.


Set owner to @nex3.

@munificent
Copy link
Member

Friendly ping! Is this being worked on by anyone?

@DartBot
Copy link

DartBot commented Jul 17, 2014

This comment was originally written by LukeEC...@gmail.com


I'm with the users who are experiencing this problem. Is there any more data that I can help to gather?

@nex3
Copy link
Member

nex3 commented Jul 22, 2014

Issue #20130 has been merged into this issue.

@nex3
Copy link
Member

nex3 commented Jul 24, 2014

r38532 works around this in http_multi_server and thus pub, but we'd really like to see a fix in dart:io.


Removed the owner.
Removed this from the 1.6 milestone.
Removed Priority-Critical, C7, Area-Pub labels.
Added Priority-Unassigned, Area-Library, Library-IO, Triaged labels.

@DartBot
Copy link

DartBot commented Jul 27, 2014

This comment was originally written by robert.w.hart...@gmail.com


It looks like I can't even run "pub build". Why does pub build need a socket? Anyway I can workaround this to get my project build?

@andersjohnsen
Copy link
Author

Proposed CL: https://codereview.chromium.org/426613002/


Set owner to @skabet.
Added Started label.

@andersjohnsen
Copy link
Author

CL is landed. It would be great if we can get some feedback on this, from a system where it's actually reproducible.


Added C7, NeedsInfo labels.

@andersjohnsen andersjohnsen added Type-Defect area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io os-windows labels Jul 28, 2014
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io os-windows
Projects
None yet
Development

No branches or pull requests

8 participants