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
panic: listen udp :50007: bind: address already in use #15
Comments
The UDP socket is not truly closed until all Conns are closed. If the process is destroyed, that is sufficient. It may be that you need to alter your torrent.Client to use a dynamic port if you are running more than one Client on a single host. |
I'm using one client, but I need to restart it. And when I Close/Create I'm getting this error. |
I should expose Destroy, that forces immediate closure of utp.Conn's bound to the Socket, and a Close of the underlying net.UDPConn. Feel free to make PR for something like this or I'll get around to it. |
I don't see this behaviour on basic tests, even if I force reuse of the same port. What OS? Can you provide a test case? |
Mac OSX, Android. You have to have some active connections, so utp.Socket.Close() will return from lazyDestroy() on len(s.conns) != 0. Easy to reproduce with your go.torrent client. Or create some code like this: package main
import (
"fmt"
"github.com/anacrolix/utp"
)
func main() {
s, err := utp.NewSocket("udp", ":5555")
fmt.Println(err)
go func() {
s.Accept()
}()
c, err := utp.NewSocket("udp", ":4444")
fmt.Println(err)
c.Dial(":5555")
s.Close()
s, err = utp.NewSocket("udp", ":5555")
fmt.Println(err)
s.Close()
c.Close()
} |
@axet Yes but this is currently by intention. In your test code above, you've leaked the net.Conns returned from c.Dial, and s.Accept(). The current design is that the udp net.PacketConn won't be closed until both the Socket, and all its Conns are closed. If you could make a test case where this occurs, and yet the udp PacketConn isn't closed? |
Current uTP socket implementation has side effect where you create object, close it and unable to create it again. This test case leaking connections by purpose, since in real world you not able to control other side so connection can stay alive for some time. Creating test case one one machine where you create and close all connections has no point. Because next we have to create test case where we emulate remote host which keeps connection. And yet, it is possible to create such test. We just need close socket, but not send anything. Result: all sockets will be closed, but few conn's will be alive. |
I created a test, where the remote socket abruptly disappears. After 15s (the send timeout for the FIN sent by the local Conn), the local Socket is destroyed, and the underlying PacketConn closed. Interestingly, even if I force the PacketConn to be closed right away, I can't listen successfully right away, I get |
This happens because golang works strange with sockets, It should add use SO_REUSEADDR. This library works: |
This is UDP, reuseaddr has no meaning in context of udp |
Well I've added a test, that should be adaptable to the desired behaviour for Close, or to test a new method like Destroy or something. |
Have you tried waiting 15-20s for your torrent.Client's UDP connection to be lazily destroyed and reclaimed by the OS? Does that work? Alternatively, restart the process? Is that feasible? |
Not sure what the thumbs down is for, reuseport for UDP is only useful for multicast subscriptions, allowing multiple processes to subscribe. It also has no effect for nornal UDP connections. |
@AudriusButkevicius you were right. I have to read about UDP more. I expect this code will throw exception. import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 5005))
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 5005))
while True:
data, addr = sock.recvfrom(1024)
print "received message:", data |
@anacrolix Last time I tried it failed, and I moved to automatic port ":0". |
There are 3 solutions here:
Solution 2 seems the best, and I think matches @axet's requirements. There'd be some work to ensure the immediate close triggers all the Socket's utp.Conn to send FINs wherever possible before the net.PacketConn is closed and that becomes no longer possible. If there's a consensus, I'll create a new method that closes immediately with the above behaviour. I'm not sure what's a good name, Socket.Destroy, CloseNow, DestroyNow, CloseImmediately, something like that. Is there a precedent for naming this? |
I have been running into this same issue. #2 sounds like the right solution to me. I think this method should attempt to block until the underlying socket has been closed by the OS. After doing some experimenting locally (Darwin) it looks like Go won't actually call the Example: https://gist.github.com/prettymuchbryce/ee7a74fe1905dd29190e8f91dc822e88 After the FINs are sent we could make sure with a |
A blocking CloseNow with the behaviour you described sounds ideal. A test that creates a Socket, then calls CloseNow and immediately tries to create a new Socket on the same address, similar to what is happening in your gist should also be included. If someone wants to do a PR for this, that would be great. I might not have time or the resources to do it myself for a week or two. |
@anacrolix still crashing |
Would that be
in |
@anacrolix it works. |
Not sure what is the reason you do not call SO_REUSEADDR or lazyDestroy() does the job but I unable to restart application. Especially It hurts on Android.
Can you make Socket.destroy() exported if it helps? Or how to wait until socket will be destoryed?
The text was updated successfully, but these errors were encountered: