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 CCheckQueue IsIdle (potential) race condition #9495

Closed

Conversation

JeremyRubin
Copy link
Contributor

There's a small race condition in the CCheckQueue code which I don't think is currently an active issue, but future code might break.

IsIdle is not threadsafe. If two concurrent CCheckqueueControls are made, they could simultaneously report being idle, and fail to panic.

Furthermore, in the case a concurrent CCheckqueueControl is made, most likely waiting until control is relinquished is the right behavior rather than failing an assert.

@@ -185,8 +182,7 @@ class CCheckQueueControl
{
// passed queue is supposed to be unused, or NULL
if (pqueue != NULL) {
bool isIdle = pqueue->IsIdle();
assert(isIdle);
ENTER_CRITICAL_SECTION(pqueue->ControlMutex);
Copy link
Member

Choose a reason for hiding this comment

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

Can you do this as a unique_lock field inside CCheckQueueControl (so we don't need to rely on an explicit destructor to be correct)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately this is the "easiest" way to take care of this given that we want debug order & the CMutex class has no default constructor/moveable semantics. Certainly can be fixed to RAII easily later.

Copy link
Member

Choose a reason for hiding this comment

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

Understood. Let's improve that in a separate PR later.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

utACK 958ee1d3d844d1f2f07b271ad7ed9bb117e5a766 with one nit:

Would suggest deleting the CCheckQueueControl default copy constructor and copy operator and making the pqueue member const, to give more assurance that the ENTER/LEAVE calls will always be paired.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

utACK 2a58f73601ad36d0531fe9e69e1affd9229d8b96

src/checkqueue.h Outdated
if (pqueue != NULL) {
ENTER_CRITICAL_SECTION(pqueue->ControlMutex);
}
CCheckQueueControl<T>() = delete;
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I think you can drop the <T>

@JeremyRubin
Copy link
Contributor Author

Squashed and addressed @ryanofsky's nit about template args in constructors.

Copy link
Member

@sipa sipa left a comment

Choose a reason for hiding this comment

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

utACK

src/checkqueue.h Outdated
CCheckQueueControl& operator=(const CCheckQueueControl&) = delete;
explicit CCheckQueueControl(CCheckQueue<T> * const pqueueIn) : pqueue(pqueueIn), fDone(false)
{
// passed queue is supposed to be unused, or NULL
Copy link
Member

Choose a reason for hiding this comment

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

Weird indendation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops -- somehow, my expandtab and tabstop=4 got unset.

@JeremyRubin
Copy link
Contributor Author

sorry for causing extra review -- pushed and squashed indention fix.

Copy link
Member

@kallewoof kallewoof left a comment

Choose a reason for hiding this comment

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

utACK f5daff7

@@ -127,6 +127,9 @@ class CCheckQueue
}

public:
//! Mutex to ensure only one concurrent CCheckQueueControl
boost::mutex ControlMutex;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Is there some coding standard for mutexes which makes you capitalize this ivar? If not, maybe controlMutex would be more consistent.

@JeremyRubin JeremyRubin mentioned this pull request Mar 7, 2017
@JeremyRubin
Copy link
Contributor Author

#9497 was merged, which included this. Closing.

@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants