redis icon indicating copy to clipboard operation
redis copied to clipboard

Command-line --port argument does not work for some arguments

Open mehrdadn opened this issue 4 years ago • 7 comments

Hi,

For some reason, redis-server --port N does not work for some N, and this seems to be for a large (and seemingly arbitrary) set of N values that don't appear to have correlation with what my system already has open. I get bind: An operation was attempted on something that is not a socket as follows:

> redis-server --port 2055
[14520] 31 May 03:28:12.636 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
[14520] 31 May 03:28:12.636 # Redis version=5.0.9, bits=64, commit=9414ab9b, modified=0, pid=14520, just started
[14520] 31 May 03:28:12.636 # Configuration loaded
[14520] 31 May 03:28:12.646 # Could not create server TCP listening socket *:2055: bind: An operation was attempted on something that is not a socket.

> redis-server --port 2056
[8772] 31 May 03:28:14.799 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
[8772] 31 May 03:28:14.799 # Redis version=5.0.9, bits=64, commit=9414ab9b, modified=0, pid=8772, just started
[8772] 31 May 03:28:14.805 # Configuration loaded
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 5.0.9 (9414ab9b/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 2056
 |    `-._   `._    /     _.-'    |     PID: 8772
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

[8772] 31 May 03:28:14.807 # Server initialized
[8772] 31 May 03:28:14.807 * Ready to accept connections
[8772] 31 May 03:28:15.475 # User requested shutdown...
[8772] 31 May 03:28:15.475 # Redis is now ready to exit, bye bye...

I haven't had a chance to debug it through compiling the code, but one curiosity appears to be be that ioctlsocket(x, FIONBIO, ...) is called with x being both 3 and 4, both of which result in WSAENOTSOCK (which is not surprising, given they don't look like valid handles). However, this appears to occur for both working ports as well as broken ports, so I'm not sure if it's actually related. But this problem comes up for both version 4 and version 5. Would you have any guesses as to why? Thank you!

mehrdadn avatar May 31 '20 10:05 mehrdadn

It seems it gives this not-so-meaningful error message when a given port cannot be bound as it is already in use. You can test it by running redis-server.exe --port 2055 twice: image (the message is in Polish, but it is the same error).

tporadowski avatar May 31 '20 13:05 tporadowski

I will have a look though if this could be improved to show what is really going on there (port already in use).

tporadowski avatar May 31 '20 13:05 tporadowski

Thanks! I think that's not the cause here, though it does show the same error in that case. This happens to too many ports for me for them all to be in use. And I can indeed confirm they're not:

> redis-server.exe --port 2055
[3564] 31 May 06:07:42.424 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
[3564] 31 May 06:07:42.424 # Redis version=5.0.9, bits=64, commit=9414ab9b, modified=0, pid=3564, just started
[3564] 31 May 06:07:42.424 # Configuration loaded
[3564] 31 May 06:07:42.439 # Could not create server TCP listening socket *:2055: bind: An operation was attempted on something that is not a socket.

> netstat -a -n | findstr 2055

>

That said, I'm not sure if this is actually a problem with this repo, or with Redis itself, or with the Windows kernel somehow. Because I feel like I saw something similar on WSL. Though the ioctlsocket I traced in Windows didn't really make sense either, so maybe there are multiple problems?

mehrdadn avatar May 31 '20 13:05 mehrdadn

There is this RFDMap feature of mapping file descriptors to files/sockets that is kicking in here, so maybe it is passing not the right structure to bind. Anyway, one would expect to get a WSAEADDRINUSE instead of WSAENOTSOCK in case port is already in use, will investigate that - thanks for reporting this!

tporadowski avatar May 31 '20 14:05 tporadowski

So I got a chance to look into this, and it seems there are indeed 2 issues. One is in anetListen:

if (bind(s,sa,len) == -1) {
    anetSetError(err, "bind: %s", IF_WIN32(wsa_strerror(errno), strerror(errno)));

It's checking errno for some reason when in fact it should be checking WSAGetLastError().

The actual error is, in fact, WSAEACCES. For some reason, I can't bind to some ports (like 2048) on my system with AF_INET6, but I can with AF_INET. It appears these ports are reserved ("excluded") on my machine, but I have no idea why:

> netsh int ipv6 show excludedportrange tcp

Protocol tcp Port Exclusion Ranges

Start Port    End Port
----------    --------
<snip>
      1956        2055
<snip>

Is there a way to force IPv4-only with Redis? If not, should there be something to allow that?

mehrdadn avatar Jun 01 '20 11:06 mehrdadn

For me it shows only port 5357. As for falling back to IPv4 - I think I've seen something that should try it, but perhaps it works differently on Windows - will check that, too.

tporadowski avatar Jun 01 '20 13:06 tporadowski

Interesting. It turns out this is due to Hyper-V. Uninstalling the feature removes the port reservations.

mehrdadn avatar Jun 11 '20 22:06 mehrdadn