Skip to content

python: keep stream and engine alive for callbacks#1379

Merged
goaway merged 14 commits intomainfrom
ch/callback-lifetimes
May 19, 2021
Merged

python: keep stream and engine alive for callbacks#1379
goaway merged 14 commits intomainfrom
ch/callback-lifetimes

Conversation

@crockeo
Copy link
Contributor

@crockeo crockeo commented Apr 14, 2021

Description: Modifies the ownership model of objects so that callbacks keep their relevant parent alive (EngineCallbacks -> Engine; StreamCallbacks -> Stream) instead of the other way around.

This PR assumes that one of StreamCallbacks terminal callbacks will be called exactly once (on_complete, on_error, on_cancel) and that on_exit will be called exactly once. If these are called more than once there will be a double free, if they are not called once we'll leak memory. This is obviously not good 🙂

Risk Level: Low

Testing: bazel test //test/python/integration:test_lifetimes

Docs Changes: N/A

Release Notes: N/A

@crockeo crockeo marked this pull request as draft April 14, 2021 04:05
@crockeo crockeo force-pushed the ch/callback-lifetimes branch from 0a00df3 to 53a46a4 Compare April 15, 2021 00:08
Signed-off-by: Cerek Hillen <chillen@lyft.com>
@crockeo crockeo force-pushed the ch/callback-lifetimes branch from 44263e7 to 3b7f3e7 Compare April 16, 2021 15:14
…lback-lifetimes

Signed-off-by: Cerek Hillen <chillen@lyft.com>
@crockeo crockeo marked this pull request as ready for review April 16, 2021 15:17
@crockeo
Copy link
Contributor Author

crockeo commented Apr 16, 2021

Marking as ready for review because I want feedback on this strategy. I'm kind of fumbling around in the dark, so I'm sure there's a better way.

.log = nullptr,
.release = envoy_noop_release,
.context = nullptr,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Would need to verify, but by convention, it should be safe to simply calloc this (or any other envoy mobile struct) if you're not going to use it.

goaway
goaway previously approved these changes May 6, 2021
Copy link
Contributor

@goaway goaway left a comment

Choose a reason for hiding this comment

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

Nice work, lgtm.

crockeo added 2 commits May 8, 2021 15:34
…lback-lifetimes

Signed-off-by: Cerek Hillen <chillen@lyft.com>
Signed-off-by: Cerek Hillen <chillen@lyft.com>
crockeo and others added 9 commits May 11, 2021 17:06
…lback-lifetimes

Signed-off-by: Cerek Hillen <chillen@lyft.com>
Signed-off-by: Cerek Hillen <chillen@lyft.com>
Signed-off-by: Cerek Hillen <chillen@lyft.com>
…lback-lifetimes

Signed-off-by: Cerek Hillen <chillen@lyft.com>
Signed-off-by: Cerek Hillen <chillen@lyft.com>
Signed-off-by: Cerek Hillen <chillen@lyft.com>
…lback-lifetimes

Signed-off-by: Cerek Hillen <chillen@lyft.com>
Signed-off-by: Cerek Hillen <chillen@lyft.com>
// which can't be provided from inside of the constructor
// because of how std::enable_shared_from_this works
StreamClientSharedPtr Engine::streamClient() {
if (!this->stream_client_) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like it's not going to be thread-safe. If we need to use lazy clients, we should maybe just create a new one every time someone asks for one. It's not an especially heavyweight object anyways.

// because of how std::enable_shared_from_this works
StreamClientSharedPtr Engine::streamClient() {
if (!this->stream_client_) {
this->stream_client_ = std::make_shared<StreamClient>(this->weak_from_this());
Copy link
Contributor

Choose a reason for hiding this comment

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

I think StreamClient should probably take a shared reference to the Engine rather than a weak one. We made stats weak so that all the stats objects that might be distributed around a program wouldn't all be retaining the engine... but then again, it's up for debate whether they should be, as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

(Also FWIW, it does effectively take a shared ref in the other platforms.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a weak ptr to avoid a cycle (Engine -> StreamClient -> Engine), but I don't think this cycle needs to exist anymore. It's just a byproduct of the original design of this PR where Streams kept Engines alive.

I can address this comment along with the earlier comment at the same time, I think, by just removing the EngineSharedPtr references throughout StreamClient and StreamPrototype and just move them back to envoy_engine_t

Signed-off-by: Cerek Hillen <chillen@lyft.com>
@goaway goaway merged commit 5d05672 into main May 19, 2021
@goaway goaway deleted the ch/callback-lifetimes branch May 19, 2021 21:25
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.

2 participants