-
Notifications
You must be signed in to change notification settings - Fork 993
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
Fix netProbe write check #843
Conversation
Write at least 1 byte. This ensures that sockets are ready to use for writing. Windows specific: during the system startup, sockets can be created but the underlying buffers may not be setup yet. If this is the case Write fails with WSAENOBUFS: "An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full This fixes: #841
This is a Windows-specific issue, so we should do this only on Windows (and only if the netprobe timeout is not 0). This contradicts the documentation and configuration file saying that nothing is ever sent to this address. Such a change will trigger alarms from local firewalls, little snitch and friends, so this should be documented. |
Good points. According to the MS documentation, a winsock send call with len = 0 bytes also sends a datagram: I don't know what the Go implementation does (maybe it does nothing if len = 0) because I cannot explain why it would succeed with len 0, but not with len 1. Maybe the whole network code (config.loadSources) should be executed in the service thread and not during the service startup on Windows. |
It's a little bit weird that the behavior differs with an empty message and with a one-byte message. I think an empty datagram is a valid datagram, so Go shouldn't handle this differently. Or maybe this is an interesting bug. Raw syscalls are available in Go so maybe we should try these directly? |
The problem is (at least on Windows) that the network code should not be in the service init function. The reason is that Windows will stop the service if the init does not complete within 45000 milliseconds (apparently the new default on Windows 10). So even with a reliable netProbe implementation, the current design cannot cope with all situations. For example, it is likely that it may take longer than 45 seconds to obtain network connectivity, to resolve the host and to download the sources (public-resolvers.md) from github etc. And in this case, the dnscrypt-proxy service fails to start. What I propose is something like that:
This has the following benefits:
I probably missed half of the things involved, but I think that should fix the current issues. |
Using resolvers lists and pivoting to other ones sounds complicated and dangerous. And netprobe is probably a good thing to keep. On Linux, we need to inform systemd that the service started. Trying to update the resolvers list in a loop will either be slow or hammer servers if something goes wrong. The only thing we need for Windows services is return as soon as possible. So that the service does nothing but spawns a goroutine that does everything. And that goroutine can be the same on all operating systems, for all commands (including commands such as I quickly tried to do that but eventually gave up due to implementation details of the |
Write at least 1 byte. This ensures that sockets are ready to use for writing.
Windows specific: during the system startup, sockets can be created but the underlying buffers may not be setup yet. If this is the case Write fails with WSAENOBUFS: "An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full
This fixes: #841