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

Fix segfault caused by modifying list within iteration. #922

Merged
merged 2 commits into from
May 8, 2017

Conversation

dnoe
Copy link
Contributor

@dnoe dnoe commented May 8, 2017

A segfault arose when iterating over the list of
secondary_init_clusters_ and calling initialize(). The call to
initialize may result in the initialized item being removed from the
secondary_init_clusters_ list while walking through the list. The
initialized item can only remove itself, not any other item in the
list. However, this resulted in chasing an invalidated iterator when
trying to go to the next element in the list.

To fix this the loop is modified so that the iterator is advanced to the
next item (or end() if no more items) before calling
Cluster::initialize().

A test is included which exercises this scenario

Fixes #903

A segfault arose when iterating over the list of
secondary_init_clusters_ and calling initialize().  The call to
initialize may result in the initialized item being removed from the
secondary_init_clusters_ list while walking through the list.  The
initialized item can only remove itself, not any other item in the
list.  However, this resulted in chasing an invalidated iterator when
trying to go to the next element in the list.

To fix this the loop is modified so that the iterator is advanced to the
next item (or end() if no more items) before calling
Cluster::initialize().

A test is included which exercises this scenario

Fixes envoyproxy#903
NiceMock<MockCluster> cluster;
// Fake that we are in the secondary InitializePhase for this test.
ON_CALL(cluster, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Secondary));
// We expect that initialize() should be called first upon addCluster. In the
Copy link
Member

Choose a reason for hiding this comment

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

The code change looks good (thanks for fixing), but I think the test and the explanation can be simplified a bit. For secondary clusters, initialize() is not called when addCluster() is called. It's called once all the primary clusters have initialized OR when static load completes if there are no primary clusters. So, I would rejigger this test to do:

ON_CALL(cluster, initializePhase())...
init_helper.addCluster(cluster);
EXPECT_CALL(cluster, initialize())... // remove inline
init_helper.onStaticLoadComplete();

Then also simplify the explanation surrounding the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, thanks! This is definitely useful. I will ensure the rejiggered test fails with the original code, and passes with the fix.

Confirmed that the test still fails with the original
maybeFinishInitialize() code, and passes with the revised safe
loop.
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Awesome thanks.

@mattklein123 mattklein123 merged commit 54d724b into envoyproxy:master May 8, 2017
rshriram pushed a commit to rshriram/envoy that referenced this pull request Oct 30, 2018
* Update envoy to 352fe35

* fix format
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.

Bad SDS Host URL causes seg fault
2 participants