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

Clean up libuv connection #1726

Merged
merged 2 commits into from
Apr 21, 2017
Merged

Clean up libuv connection #1726

merged 2 commits into from
Apr 21, 2017

Conversation

davidfowl
Copy link
Member

  • Cancel all pending flushes on the input writer before
    disposing the stream handle.
  • Complete the pipe before disposing the socket
  • Added logging for connection pause/resume.
  • Added test

Input.Complete();
}
}
_socket.ReadStart(_allocCallback, _readCallback, this);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add the try catch back but I'd like to understand if it's truly needed (and write a test for it maybe).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this could fail for the same reason that uv_tcp_getpeername sometimes does on linux. This is normally caught and logged by the listener instead of crashing the server, but that wouldn't be the case for Resume().

Remember that before Resume() is called there is no read callback wired to tell us the underlying connection is no closed or invalid.

Input.Complete();
}
}
_socket.ReadStart(_allocCallback, _readCallback, this);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this could fail for the same reason that uv_tcp_getpeername sometimes does on linux. This is normally caught and logged by the listener instead of crashing the server, but that wouldn't be the case for Resume().

Remember that before Resume() is called there is no read callback wired to tell us the underlying connection is no closed or invalid.

_socket.Dispose();
// Make sure it isn't possible for a paused read to resume reading after calling uv_close
// on the stream handle
Input.CancelPendingFlush();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a Pipe test that verifies that the writer in fact observes cancellation when:

  1. The writer continuation is scheduled after a call to IPipeReader.Advance.
  2. Next CancelPendingFlush is called.
  3. Lastly the _writerScheduler actually runs the continuation.

It looks like this is already the case, but it's important this never regresses.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

[Fact]
public async Task ConnectionDoesNotResumeAfterSocketCloseIfBackpressureIsApplied()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test actually consume the "request" data in such a way that the old code would have even tried to resume? Looking at the test, it seems like it would pass in dev since (await flushTask).IsCompleted would already be true.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(await flushTask).IsCompleted is never true be cause we never complete the Input.Reader. Regardless, I'm attempting to add another test.

var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler };
var transport = new LibuvTransport(mockLibuv, transportContext, null);
var thread = new LibuvThread(transport);
// We don't set the output scheduler here since we want to run the callback inline
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: We don't set the output writer scheduler

Copy link
Member

@halter73 halter73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks better than I thought. Mostly nits.

@davidfowl davidfowl force-pushed the davidfowl/libuv-connection branch from 6055194 to 32dafb0 Compare April 21, 2017 06:36
@davidfowl
Copy link
Member Author

🆙 📅

- Cancel all pending flushes on the input writer before
disposing the stream handle.
- Complete the pipe before disposing the socket
- Added logging for connection pause/resume.
- Added test
@davidfowl davidfowl force-pushed the davidfowl/libuv-connection branch from 32dafb0 to 99403b6 Compare April 21, 2017 09:03
// ReadStart() can throw a UvException in some cases (e.g. socket is no longer connected).
// This should be treated the same as OnRead() seeing a "normalDone" condition.
Log.ConnectionReadFin(ConnectionId);
Input.Complete();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ironically, this is the only place the input writer is completed without an error. You could fix #1331 right now by calling Input.Complete(uvEx) here.

@@ -132,7 +132,7 @@ private void OnConnection(UvStreamHandle listenSocket, int status)
protected virtual void DispatchConnection(UvStreamHandle socket)
{
var connection = new LibuvConnection(this, socket);
connection.Start();
_ = connection.Start();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Soo much better than async void lol.

@davidfowl davidfowl merged commit a749939 into dev Apr 21, 2017
@davidfowl davidfowl deleted the davidfowl/libuv-connection branch April 25, 2017 00:38
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants