Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove "-t" enforcement in C++, simplify ConnectTimeout / CloseTimeout #2059

Merged
merged 7 commits into from
Apr 24, 2024

Conversation

bernardnormier
Copy link
Member

This PR removes the "-t" (connection timeout) enforcement in C++. It also simplifies the implementation for ConnectTimeout and CloseTimeout, and removes the special deprecated "-2" invocation timeout.

@@ -610,38 +610,6 @@ allTests(Test::TestHelper* helper, const CommunicatorObserverIPtr& obsv)

metrics->ice_getConnection()->close(Ice::ConnectionClose::GracefullyWithWait);

metrics->ice_timeout(500)->ice_ping();
Copy link
Member Author

@bernardnormier bernardnormier Apr 18, 2024

Choose a reason for hiding this comment

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

It would be good to add back a metrics test that tests connection failures. It's not clear to me how to do it. I'll create an issue .

Copy link
Member

Choose a reason for hiding this comment

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

It's actually not totally clear to me why this test is no longer working.

@@ -2685,10 +2702,14 @@ Ice::ConnectionI::sendResponse(OutgoingResponse response, uint8_t compress)
bool
Ice::ConnectionI::initialize(SocketOperation operation)
{
if (_connectTimeout > chrono::seconds::zero())
Copy link
Member

Choose a reason for hiding this comment

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

Isn't it possible for initialize to be called multiple times?

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 think it's possible but so rare that we don't need to optimize for the case where it's called multiple times.

If it's called multiple times, we schedule multiple connect timer tasks.

Copy link
Member

Choose a reason for hiding this comment

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

But isn't it an error to schedule a timeout, which is already scheduled?

Copy link
Member

Choose a reason for hiding this comment

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

To be clear if we return false from

if (s != SocketOperationNone)
{
    _threadPool->update(shared_from_this(), operation, s);
    return false;
}

This method would be called again, and the timer schedule would throw

if (!inserted)
{
    throw std::invalid_argument("task is already scheduled");
}

Copy link
Member Author

@bernardnormier bernardnormier Apr 22, 2024

Choose a reason for hiding this comment

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

That's not the case because we schedule a different timer task each time. It's created by make_shared:

_timer->schedule(make_shared<ConnectTimerTask>(shared_from_this()), _connectTimeout);

Copy link
Member

@bentoi bentoi left a comment

Choose a reason for hiding this comment

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

The setup of the connect timer task doesn't look correct.

cpp/src/Ice/ConnectionI.cpp Outdated Show resolved Hide resolved
@@ -2559,6 +2550,11 @@ Ice::ConnectionI::initiateShutdown()
os.write(static_cast<uint8_t>(1)); // compression status: compression supported but not used.
os.write(headerSize); // Message size.

if (_closeTimeout > chrono::seconds::zero())
Copy link
Member

Choose a reason for hiding this comment

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

We will need to document the change of behavior, for both connect and close timeouts.

Previously, the close timeout didn't apply to the whole period of the connection closure. It applied to the period between two transport operations. So as long as there was transport activity while in the closing state, the connection wouldn't timeout. Ditto for connection establishment.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. Keep in mind the properties are new (compared to Ice 3.7) and the semantics match IceRPC's semantics for connect and shutdown timeout.

@@ -2685,10 +2702,14 @@ Ice::ConnectionI::sendResponse(OutgoingResponse response, uint8_t compress)
bool
Ice::ConnectionI::initialize(SocketOperation operation)
{
if (_connectTimeout > chrono::seconds::zero())
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is the right place for scheduling the connect timer task. It should be moved to the implementation of startAsync only if the connection establishment doesn't complete right away.

Copy link
Member Author

Choose a reason for hiding this comment

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

Moved to startAsync as suggested.

@@ -610,38 +610,6 @@ allTests(Test::TestHelper* helper, const CommunicatorObserverIPtr& obsv)

metrics->ice_getConnection()->close(Ice::ConnectionClose::GracefullyWithWait);

metrics->ice_timeout(500)->ice_ping();
Copy link
Member

Choose a reason for hiding this comment

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

It's actually not totally clear to me why this test is no longer working.

controller->holdAdapter(-1);
try
{
to->sendData(seq);
Copy link
Member

Choose a reason for hiding this comment

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

Do we have a similar test for the new idle timeout? I suppose that if the connection writes are stuck in both directions the connection is not killed?

Copy link
Member Author

@bernardnormier bernardnormier Apr 22, 2024

Choose a reason for hiding this comment

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

That's correct. With this update, a write can get stuck forever. We actually have exactly the same semantics with IceRPC: with IceRPC, the only way to interrupt a stuck write with the ice protocol is to abort the connection.

The assumption here (and in IceRPC) is if the connection is sick and writes are stuck, the idle check will abort the connection (locally or in the peer). We should indeed add a test to verify the idle check can indeed abort a connection when this connection is stuck writing.

Copy link
Member Author

Choose a reason for hiding this comment

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

The removed portion of the metrics test (as I understand it) was generating connection errors by having write hang because of a low "-t" (500 ms). Since this feature (-t) is removed by this PR, this no longer works.

@bernardnormier
Copy link
Member Author

bernardnormier commented Apr 23, 2024

@bentoi, can you please review the work-around I added to the Ice/metrics test?

Copy link
Member

@bentoi bentoi left a comment

Choose a reason for hiding this comment

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

Looks good.

@bernardnormier bernardnormier merged commit 60fbf3a into zeroc-ice:main Apr 24, 2024
17 checks passed
@bernardnormier bernardnormier deleted the acm5 branch May 10, 2024 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants