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

RequestTimeout setting results in `getProtocolByName: does not exist (no such protocol name: tcp))` #374

Open
crockeea opened this issue Dec 3, 2018 · 9 comments

Comments

@crockeea
Copy link

commented Dec 3, 2018

When sending several requests using mapM_ (parseRequest ...) to different destinations, I get many errors of the form

ghc: HttpExceptionRequest Request {
  host                 = "127.0.0.1"
  port                 = 45733
  secure               = True
  requestHeaders       = []
  path                 = "/"
  queryString          = ""
  method               = "POST"
  proxy                = Nothing
  rawBody              = False
  redirectCount        = 10
  responseTimeout      = ResponseTimeoutDefault
  requestVersion       = HTTP/1.1
}
 (InternalException (HostCannotConnect "127.0.0.1" [Network.Socket.socket: resource exhausted (Too many open files)]))
ghc: HttpExceptionRequest Request {
  host                 = "127.0.0.1"
  port                 = 40299
  secure               = True
  requestHeaders       = []
  path                 = "/"
  queryString          = ""
  method               = "POST"
  proxy                = Nothing
  rawBody              = False
  redirectCount        = 10
  responseTimeout      = ResponseTimeoutDefault
  requestVersion       = HTTP/1.1
}
 (ConnectionFailure Network.BSD.getProtocolByName: does not exist (no such protocol name: tcp))

This sounds like #307, but I'm only sending 25 requests, which hardly seems like DOS. Furthermore, I noticed that if I set the Manager's managerResponseTimeout=responseTimeoutNone, I do not get any errors (everything works fine). After inspecting and playing with getConnectionWrapper in Network.HTTP.Client.Core, I see absolutely no reason why changing this setting affects this error. Yet it does, every single time.

There are several questions:

  1. Why does changing the timeout setting affect whether I can call getProtocolbyName/run out of file descriptors?
  2. I'm apparently getting multiple errors for each request I send (about 20 errors for each request, most of which are identical), which makes weeding through errors much harder. Why is that happening?
  3. What is the root cause here?
@crockeea

This comment has been minimized.

Copy link
Author

commented Dec 3, 2018

I should note that the errors occur just a few seconds after calling parseRequest, long before any relevant timeouts should even be triggered. This makes it extra suspicious that changing the request timeout affects the behavior.

@crockeea crockeea changed the title Connection Timeout results in `getProtocolByName: does not exist (no such protocol name: tcp))` RequestTimeout setting results in `getProtocolByName: does not exist (no such protocol name: tcp))` Dec 3, 2018
@snoyberg

This comment has been minimized.

Copy link
Owner

commented Dec 4, 2018

@crockeea

This comment has been minimized.

Copy link
Author

commented Dec 4, 2018

I would be very interested to learn why timeouts matter. I would like to enforce a timeout, but I'm unable to do so due to running out of file descriptors. It doesn't seem like I should be anywhere near the limit, so it seems like timeouts are somehow affecting the fds usage.

@snoyberg

This comment has been minimized.

Copy link
Owner

commented Dec 5, 2018

It's possible that the System.Timeout.timeout call itself is using some additional file descriptors, I'm not sure. Unfortunately I won't have time myself to dig into this puzzle any time soon, but I'd also love to find out what's happening.

@domenkozar

This comment has been minimized.

Copy link

commented Sep 18, 2019

It seems like network module is calling https://hackage.haskell.org/package/network-bsd-2.8.1.0/docs/Network-BSD.html#v:getProtocolByName on each connect call, which seems quite wasteful.

@domenkozar

This comment has been minimized.

Copy link

commented Sep 18, 2019

Which is hidden behind getProtocolNumber, but that changed in network-3, so needs further investigation.

@domenkozar

This comment has been minimized.

Copy link

commented Sep 18, 2019

@crockeea I'm willing to dig into this if you give me code to reproduce it.

@domenkozar

This comment has been minimized.

Copy link

commented Sep 27, 2019

My conclusion is that network-3 has been refactored to avoid these lookups, so it should use fewer file handles.

I suggest upgrading to network-3 if you hit these issues. Sadly it hasn't been bumped on stackage since May

@domenkozar

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.