Skip to content

Commit

Permalink
SERVER-36885: Make ASIO remember IOCP state when out of resources
Browse files Browse the repository at this point in the history
  • Loading branch information
spencerjackson committed Sep 18, 2018
1 parent e65ff57 commit 67ab3ae
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ void win_iocp_io_context::post_deferred_completion(win_iocp_operation* op)
op->ready_ = 1;

// Enqueue the operation on the I/O completion port.
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op))
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
Expand All @@ -272,7 +272,7 @@ void win_iocp_io_context::post_deferred_completions(
op->ready_ = 1;

// Enqueue the operation on the I/O completion port.
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op))
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
Expand All @@ -298,9 +298,10 @@ void win_iocp_io_context::on_pending(win_iocp_operation* op)
{
if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
{
op->completionKey() = overlapped_contains_result;
// Enqueue the operation on the I/O completion port.
if (!::PostQueuedCompletionStatus(iocp_.handle,
0, overlapped_contains_result, op))
0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
Expand All @@ -322,9 +323,11 @@ void win_iocp_io_context::on_completion(win_iocp_operation* op,
op->Offset = last_error;
op->OffsetHigh = bytes_transferred;


// Enqueue the operation on the I/O completion port.
op->completionKey() = overlapped_contains_result;
if (!::PostQueuedCompletionStatus(iocp_.handle,
0, overlapped_contains_result, op))
0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
Expand All @@ -344,9 +347,11 @@ void win_iocp_io_context::on_completion(win_iocp_operation* op,
op->Offset = ec.value();
op->OffsetHigh = bytes_transferred;


// Enqueue the operation on the I/O completion port.
op->completionKey() = overlapped_contains_result;
if (!::PostQueuedCompletionStatus(iocp_.handle,
0, overlapped_contains_result, op))
0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,19 @@ class win_iocp_operation
func_(0, this, asio::error_code(), 0);
}

ULONG_PTR& completionKey() {
return completionKey_;
}

protected:
typedef void (*func_type)(
void*, win_iocp_operation*,
const asio::error_code&, std::size_t);

win_iocp_operation(func_type func)
: next_(0),
func_(func)
func_(func),
completionKey_(0)
{
reset();
}
Expand All @@ -76,6 +81,7 @@ class win_iocp_operation
OffsetHigh = 0;
hEvent = 0;
ready_ = 0;
completionKey_ = 0;
}

private:
Expand All @@ -84,6 +90,7 @@ class win_iocp_operation
win_iocp_operation* next_;
func_type func_;
long ready_;
ULONG_PTR completionKey_;
};

} // namespace detail
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
From 28c949880a45147d5cb9d1af16dea7494f68f109 Mon Sep 17 00:00:00 2001
From: Spencer Jackson <spencer.jackson@mongodb.com>
Date: Mon, 17 Sep 2018 18:12:33 -0400
Subject: [PATCH] [PATCH] MONGO: Fix IOCP out of resource handling

---
.../asio/detail/impl/win_iocp_io_context.ipp | 15 ++++++++++-----
asio/include/asio/detail/win_iocp_operation.hpp | 9 ++++++++-
2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/asio/include/asio/detail/impl/win_iocp_io_context.ipp b/asio/include/asio/detail/impl/win_iocp_io_context.ipp
index c371b86b..ebb4b62b 100644
--- a/asio/include/asio/detail/impl/win_iocp_io_context.ipp
+++ b/asio/include/asio/detail/impl/win_iocp_io_context.ipp
@@ -250,11 +250,11 @@ void win_iocp_io_context::post_deferred_completion(win_iocp_operation* op)
{
// Flag the operation as ready.
op->ready_ = 1;

// Enqueue the operation on the I/O completion port.
- if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op))
+ if (!::PostQueuedCompletionStatus(iocp_.handle, 0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
completed_ops_.push(op);
::InterlockedExchange(&dispatch_required_, 1);
@@ -270,11 +270,11 @@ void win_iocp_io_context::post_deferred_completions(

// Flag the operation as ready.
op->ready_ = 1;

// Enqueue the operation on the I/O completion port.
- if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op))
+ if (!::PostQueuedCompletionStatus(iocp_.handle, 0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
completed_ops_.push(op);
completed_ops_.push(ops);
@@ -296,13 +296,14 @@ void win_iocp_io_context::abandon_operations(

void win_iocp_io_context::on_pending(win_iocp_operation* op)
{
if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
{
+ op->completionKey() = overlapped_contains_result;
// Enqueue the operation on the I/O completion port.
if (!::PostQueuedCompletionStatus(iocp_.handle,
- 0, overlapped_contains_result, op))
+ 0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
completed_ops_.push(op);
::InterlockedExchange(&dispatch_required_, 1);
@@ -320,13 +321,15 @@ void win_iocp_io_context::on_completion(win_iocp_operation* op,
op->Internal = reinterpret_cast<ulong_ptr_t>(
&asio::error::get_system_category());
op->Offset = last_error;
op->OffsetHigh = bytes_transferred;

+
// Enqueue the operation on the I/O completion port.
+ op->completionKey() = overlapped_contains_result;
if (!::PostQueuedCompletionStatus(iocp_.handle,
- 0, overlapped_contains_result, op))
+ 0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
completed_ops_.push(op);
::InterlockedExchange(&dispatch_required_, 1);
@@ -342,13 +345,15 @@ void win_iocp_io_context::on_completion(win_iocp_operation* op,
// Store results in the OVERLAPPED structure.
op->Internal = reinterpret_cast<ulong_ptr_t>(&ec.category());
op->Offset = ec.value();
op->OffsetHigh = bytes_transferred;

+
// Enqueue the operation on the I/O completion port.
+ op->completionKey() = overlapped_contains_result;
if (!::PostQueuedCompletionStatus(iocp_.handle,
- 0, overlapped_contains_result, op))
+ 0, op->completionKey(), op))
{
// Out of resources. Put on completed queue instead.
mutex::scoped_lock lock(dispatch_mutex_);
completed_ops_.push(op);
::InterlockedExchange(&dispatch_required_, 1);
diff --git a/asio/include/asio/detail/win_iocp_operation.hpp b/asio/include/asio/detail/win_iocp_operation.hpp
index 81d43f07..e0cbcc56 100644
--- a/asio/include/asio/detail/win_iocp_operation.hpp
+++ b/asio/include/asio/detail/win_iocp_operation.hpp
@@ -49,18 +49,23 @@ public:
void destroy()
{
func_(0, this, asio::error_code(), 0);
}

+ ULONG_PTR& completionKey() {
+ return completionKey_;
+ }
+
protected:
typedef void (*func_type)(
void*, win_iocp_operation*,
const asio::error_code&, std::size_t);

win_iocp_operation(func_type func)
: next_(0),
- func_(func)
+ func_(func),
+ completionKey_(0)
{
reset();
}

// Prevents deletion through this type.
@@ -74,18 +79,20 @@ protected:
InternalHigh = 0;
Offset = 0;
OffsetHigh = 0;
hEvent = 0;
ready_ = 0;
+ completionKey_ = 0;
}

private:
friend class op_queue_access;
friend class win_iocp_io_context;
win_iocp_operation* next_;
func_type func_;
long ready_;
+ ULONG_PTR completionKey_;
};

} // namespace detail
} // namespace asio

--
2.19.0

0 comments on commit 67ab3ae

Please sign in to comment.