Fix Ethernet receiver teardown race - #876
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
/azp run mscclpp-ut |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Fixes Ethernet receiver teardown races by separating socket shutdown from descriptor closure.
Changes:
- Adds exact-read outcomes and non-closing socket shutdown.
- Publishes receiver failures and safely joins before closing descriptors.
- Adds teardown/EOF tests and migrates socket logging.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/core/bootstrap/socket.cc |
Implements shutdown and exact-read handling. |
src/core/connection.cc |
Reorders teardown and propagates receiver errors. |
src/core/include/connection.hpp |
Adds receiver lifecycle/error state. |
src/core/include/socket.h |
Declares receive results and shutdown API. |
test/unit/socket_tests.cc |
Adds socket framing and teardown tests. |
Suppressed comments (1)
test/unit/socket_tests.cc:153
descriptorReusedis effectively guaranteed whenever/dev/nullopens successfully:dup2succeeds even whenreceiverFdis still open because it silently closes the target first. As a result, this assertion cannot verify thatclose()released the receiver descriptor; check forEBADFdirectly instead.
int reuseFd = ::open("/dev/null", O_RDONLY);
const bool descriptorReused = reuseFd == receiverFd || (reuseFd >= 0 && ::dup2(reuseFd, receiverFd) == receiverFd);
if (reuseFd >= 0 && reuseFd != receiverFd) ::close(reuseFd);
if (descriptorReused) ::close(receiverFd);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| void EthernetConnection::write(RegisteredMemory dst, uint64_t dstOffset, RegisteredMemory src, uint64_t srcOffset, | ||
| uint64_t size) { | ||
| rethrowReceiverError(); |
There was a problem hiding this comment.
We will check the exception at the begin and the end of the function. Can we use a warper to make it simple?
For example:
template <typename Operation>
void runWithReceiverErrorCheck(Operation&& operation) {
rethrowReceiverError(); // Failure already published before operation.
std::forward<Operation>(operation)();
rethrowReceiverError(); // Failure published while operation was running.
}
void EthernetConnection::flush(int64_t timeout) {
runWithReceiverErrorCheck([&] {
// Existing flush implementation.
});
}Or other splution
There was a problem hiding this comment.
Added runWithReceiverErrorCheck and wrapped write, updateAndSync, and flush so each operation checks the receiver error before and after execution.
|
/azp run mscclpp-ut |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Summary
Validation