Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit 2041e4d

Browse files
committed
Prevent pipes from being closed prematurely on OS X and Linux
This change fixes the in-process marshalling of TCP handles on Mac and Linux that is used to support having multiple threads accepting connections from multiple loops. On these two platforms, the ReadStart callback somtimes gets called with a status and pipe_pending_count equal to zero. Now when the status is zero just exit the callback without closing the pipe. This change more closely follows the example at https://nikhilm.github.io/uvbook/processes.html#sending-file-descriptors-over-pipes
1 parent 8a64953 commit 2041e4d

File tree

5 files changed

+35
-6
lines changed

5 files changed

+35
-6
lines changed

src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@
33

44
using System;
55
using System.Diagnostics;
6+
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
67
using Microsoft.AspNet.Server.Kestrel.Networking;
78

89
namespace Microsoft.AspNet.Server.Kestrel.Http
910
{
1011
public class Connection : ConnectionContext, IConnectionControl
1112
{
12-
private const int EOF = -4095;
13-
private const int ECONNRESET = -4077;
14-
1513
private static readonly Action<UvStreamHandle, int, Exception, object> _readCallback = ReadCallback;
1614
private static readonly Func<UvStreamHandle, int, object, Libuv.uv_buf_t> _allocCallback = AllocCallback;
1715

@@ -60,7 +58,7 @@ private void OnRead(UvStreamHandle handle, int status, Exception error)
6058
SocketInput.Unpin(status);
6159

6260
var normalRead = error == null && status > 0;
63-
var normalDone = status == 0 || status == ECONNRESET || status == EOF;
61+
var normalDone = status == 0 || status == Constants.ECONNRESET || status == Constants.EOF;
6462
var errorDone = !(normalDone || normalRead);
6563

6664
if (normalRead)

src/Microsoft.AspNet.Server.Kestrel/Http/ListenerSecondary.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using Microsoft.AspNet.Server.Kestrel.Networking;
54
using System;
65
using System.Diagnostics;
76
using System.Runtime.InteropServices;
87
using System.Threading.Tasks;
8+
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
9+
using Microsoft.AspNet.Server.Kestrel.Networking;
910

1011
namespace Microsoft.AspNet.Server.Kestrel.Http
1112
{
@@ -60,13 +61,26 @@ public Task StartAsync(
6061
(_1, _2, _3) => buf,
6162
(_1, status2, error2, state2) =>
6263
{
63-
if (status2 == 0)
64+
if (status2 < 0)
6465
{
66+
if (status2 != Constants.EOF)
67+
{
68+
Exception ex;
69+
Thread.Loop.Libuv.Check(status2, out ex);
70+
// TODO: Replace Trace.WriteLine with real logging
71+
Trace.WriteLine("DispatchPipe.ReadStart " + ex.Message);
72+
}
73+
6574
DispatchPipe.Dispose();
6675
Marshal.FreeHGlobal(ptr);
6776
return;
6877
}
6978

79+
if (DispatchPipe.PendingCount() == 0)
80+
{
81+
return;
82+
}
83+
7084
var acceptSocket = CreateAcceptSocket();
7185

7286
try

src/Microsoft.AspNet.Server.Kestrel/Infrastructure/Constants.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ internal class Constants
77
{
88
public const int ListenBacklog = 128;
99

10+
public const int EOF = -4095;
11+
public const int ECONNRESET = -4077;
12+
1013
/// <summary>
1114
/// Prefix of host name used to specify Unix sockets in the configuration.
1215
/// </summary>

src/Microsoft.AspNet.Server.Kestrel/Networking/Libuv.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,15 @@ unsafe public void pipe_connect(UvConnectRequest req, UvPipeHandle handle, strin
252252
Check(_uv_pipe_connect(req, handle, name, cb));
253253
}
254254

255+
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
256+
unsafe protected delegate int uv_pipe_pending_count(UvPipeHandle handle);
257+
protected uv_pipe_pending_count _uv_pipe_pending_count = default(uv_pipe_pending_count);
258+
unsafe public int pipe_pending_count(UvPipeHandle handle)
259+
{
260+
handle.Validate();
261+
return _uv_pipe_pending_count(handle);
262+
}
263+
255264
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
256265
public delegate void uv_alloc_cb(IntPtr server, int suggested_size, out uv_buf_t buf);
257266
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]

src/Microsoft.AspNet.Server.Kestrel/Networking/UvPipeHandle.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,10 @@ public void Bind(string name)
3232
{
3333
_uv.pipe_bind(this, name);
3434
}
35+
36+
public int PendingCount()
37+
{
38+
return _uv.pipe_pending_count(this);
39+
}
3540
}
3641
}

0 commit comments

Comments
 (0)