-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Background and Motivation
As part of the hot reload scenarios in .NET 6, ASP.NET Core is looking at moving the socket creation code to an external process.
Having the listen socket bound to in a separate process allows for inner-loop improvements by potentially parallelizing operations in the startup path since the OS will hold connections prior to your application calling accept. For e.g., you do not need to wait for the application to successfully start before launching your browser.
To allow binding to a socket in a different process than the listener would require a mechanism to pass the socket between processes. Normally this achieved by just forking the process and inheriting the file descriptors. Unfortunately, implementing this in .NET is slightly challenging since the O_CLOEXEC
flag is set on all Sockets. Providing an API to duplicate sockets would make this is a lot easier.
On Windows, there is already an API that wraps WSADuplicateSocket
, but unfortunately it duplicates and closes the socket. We'd need an API that just duplicates the socket.
Proposed API
namespace System.Net.Sockets
{
public partial class Socket
{
+ public SocketInformation DuplicateSocketWindows(int targetProcessId)
+ public SafeSocketHandle DuplicateSocketLinux()
}
}
I don't actually propose naming these DuplicateWindows
and DuplicateLinux
, but I couldn't think of good suggestions
Usage Examples
var ipEndPoint = new IPEndPoint(IPAddress.Loopback, port);
using var listenSocket = new Socket(ipEndPoint.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
listenSocket.Bind(ipEndPoint);
var duplicatedSocket = listenSocket.DuplicateSocketLinux();
var psi = new ProcessStartInfo("my-web-server");
psi.EnvironmentVariables["LISTEN_FD"] = duplicatedSocket.DangerousGetHandle().ToInt32().ToString();
var process = Process.Start(psi);
A fully fleshed example that uses the Windows and Linux variant:
Linux: https://github.com/shirhatti/zocket/blob/main/src/zocket/Program.cs#L52
Windows: https://github.com/shirhatti/zocket/blob/main/src/zocket/Program.cs#L90
Alternative Designs
I proposed duplicating (and not setting O_CLOEXEC
on the duplicated socket) as opposed calling fcntl on the original socket to preserve some semblance of symmetry between the Windows and Linux use cases.
This is common feature of development server in other language ecosystem: Werkzeug, Lithos, systemfd
Risks
Improper usage of this API could result in leaking file descriptors, but it's hard to mitigate that since the goal of this API is intentional leakage of the file descriptor.