Skip to content

Prevent wrong usage of Control Objects with assertions#2896

Merged
daschuer merged 16 commits intomixxxdj:2.3from
Holzhaus:co-assert
Jul 2, 2020
Merged

Prevent wrong usage of Control Objects with assertions#2896
daschuer merged 16 commits intomixxxdj:2.3from
Holzhaus:co-assert

Conversation

@Holzhaus
Copy link
Copy Markdown
Member

This should prevent CO failures from going unnoticed. Right now, only a warning is displayed in the log, which can easily be overlooked.

Zulip discussion that prompted this PR: https://mixxx.zulipchat.com/#narrow/stream/109171-development/topic/Macros.2FSaved.20Hotcue.20Routines.2F.22Serato.20Flip.22/near/201478587

@Holzhaus Holzhaus changed the base branch from master to 2.3 June 21, 2020 12:21
Comment thread src/control/control.cpp
Comment thread src/control/control.cpp Outdated
Comment thread src/control/control.h Outdated

enum class ControlFlag {
None = 0,
NoWarnIfMissing = 1,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The negation make the code harder to understand. Why not WarnIfMissing and WarnAndAssertIfMissing? Using flags is not necessary according to the code, because the assertion is nested in the warning path. Use a simple enum class instead.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I was planning on adding a few more flags, e.g. DelayedInitialization for ControlProxy objects that are created before the actual CO (e.g. [AutoDJ],enabled). Right now we just disable the warnings completely, but IMHO this is not a good solution.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Why not WarnIfMissing and WarnAndAssertIfMissing?

I wanted to make it explicit from the caller side that the warnings/assertions are disabled, so that don't set InitializeLater and accidently disable warnings/assertions because you forgot to OR this with the WarnAndAssertIfMissing flag.

Btw, I also had to add a flag to allow missing keys for WWidgetStack (which takes params from skins).

Comment thread src/controllers/controllerengine.cpp
Comment thread src/skin/legacyskinparser.cpp
@uklotzde uklotzde added this to the 2.3.0 milestone Jun 21, 2020
@uklotzde uklotzde changed the title [WIP] Improve safety of Control Objects with assertions [WIP] Prevent wrong usage of Control Objects with assertions Jun 21, 2020
@uklotzde
Copy link
Copy Markdown
Contributor

Renamed the PR to better reflect the intention.

@Holzhaus Holzhaus requested a review from uklotzde June 21, 2020 18:09
@Holzhaus Holzhaus changed the title [WIP] Prevent wrong usage of Control Objects with assertions Prevent wrong usage of Control Objects with assertions Jun 21, 2020
@Holzhaus
Copy link
Copy Markdown
Member Author

I hope everything is in order now. I feel like our CO stuff could use some refactoring, e.g. the skin system uses getControl to let skins create COs. I also removed the confusing method to change the key of a ControlProxy after creating it through the initialize method (just use a new object if you want that) and got rid of the ControlProxy constructor without key (which is apparently not needed and also not useful anymore).

Comment thread src/control/controlobject.h Outdated
Comment thread src/control/controlproxy.cpp Outdated
Comment thread src/control/controlproxy.cpp Outdated
Comment thread src/control/controlproxy.cpp Outdated
Comment thread src/control/controlproxy.h Outdated
Comment thread src/test/beatstranslatetest.cpp Outdated
Comment thread src/mixer/playermanager.cpp Outdated
Comment thread src/skin/legacyskinparser.cpp
@daschuer
Copy link
Copy Markdown
Member

Instead of Implicit disable warnings, we can introduce another function that is called getOrCreateControl() or something and maybe tryGetControl()

@daschuer
Copy link
Copy Markdown
Member

Is this really a 2.3 PR? This is not without a risk.

@Holzhaus
Copy link
Copy Markdown
Member Author

Is this really a 2.3 PR? This is not without a risk.

I think it makes sense. It adds additional safety and the additional debug assertions will be disabled in release builds anyway.

@uklotzde
Copy link
Copy Markdown
Contributor

Warning [Main]: ControlDoublePrivate::getControl returning NULL for ( "" , "visual_key_distance" )
Critical [Main]: DEBUG ASSERT: "flags.testFlag(ControlFlag::NoAssertIfMissing)" in function static QSharedPointer<ControlDoublePrivate> ControlDoublePrivate::getControl(const ConfigKey&, ControlFlags, ControlObject*, bool, bool, bool, double) at /tmp/mixxx/src/control/control.cpp:148

@uklotzde uklotzde self-requested a review June 23, 2020 22:22
Copy link
Copy Markdown
Contributor

@uklotzde uklotzde left a comment

Choose a reason for hiding this comment

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

master: Multiple debug assertions while starting Mixxx

@Holzhaus
Copy link
Copy Markdown
Member Author

master: Multiple debug assertions while starting Mixxx

You mean you pulled this branch into master?

@uklotzde
Copy link
Copy Markdown
Contributor

master: Multiple debug assertions while starting Mixxx

You mean you pulled this branch into master?

Yes, my regular development version is based on master.

@Holzhaus
Copy link
Copy Markdown
Member Author

Holzhaus commented Jun 23, 2020

I suppose this might be caused by the controller engine changes from #2682. Does this PR (based on 2.3) work for you?

@uklotzde
Copy link
Copy Markdown
Contributor

Reminder for later: The changes in ControllerEngine have to be fixed manually when merging from 2.3 into master!

Remaining debug assertions in master on startup:

Warning [Main]: ControlDoublePrivate::getControl returning NULL for ( "" , "visual_key_distance" )
Critical [Main]: DEBUG ASSERT: "flags.testFlag(ControlFlag::NoAssertIfMissing)" in function static QSharedPointer<ControlDoublePrivate> ControlDoublePrivate::getControl(const ConfigKey&, ControlFlags, ControlObject*, bool, bool, bool, double) at /tmp/mixxx/src/control/control.cpp:148
Critical [Main]: DEBUG ASSERT: "m_pControl || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:35
Critical [Main]: DEBUG ASSERT: "valid() || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:36
Warning [Main]: ControlDoublePrivate::getControl returning NULL for ( "" , "visual_key_distance" )
Critical [Main]: DEBUG ASSERT: "flags.testFlag(ControlFlag::NoAssertIfMissing)" in function static QSharedPointer<ControlDoublePrivate> ControlDoublePrivate::getControl(const ConfigKey&, ControlFlags, ControlObject*, bool, bool, bool, double) at /tmp/mixxx/src/control/control.cpp:148
Critical [Main]: DEBUG ASSERT: "m_pControl || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:35
Critical [Main]: DEBUG ASSERT: "valid() || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:36
Warning [Main]: ControlDoublePrivate::getControl returning NULL for ( "" , "visual_key_distance" )
Critical [Main]: DEBUG ASSERT: "flags.testFlag(ControlFlag::NoAssertIfMissing)" in function static QSharedPointer<ControlDoublePrivate> ControlDoublePrivate::getControl(const ConfigKey&, ControlFlags, ControlObject*, bool, bool, bool, double) at /tmp/mixxx/src/control/control.cpp:148
Critical [Main]: DEBUG ASSERT: "m_pControl || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:35
Critical [Main]: DEBUG ASSERT: "valid() || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:36
Warning [Main]: ControlDoublePrivate::getControl returning NULL for ( "" , "visual_key_distance" )
Critical [Main]: DEBUG ASSERT: "flags.testFlag(ControlFlag::NoAssertIfMissing)" in function static QSharedPointer<ControlDoublePrivate> ControlDoublePrivate::getControl(const ConfigKey&, ControlFlags, ControlObject*, bool, bool, bool, double) at /tmp/mixxx/src/control/control.cpp:148
Critical [Main]: DEBUG ASSERT: "m_pControl || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:35
Critical [Main]: DEBUG ASSERT: "valid() || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:36

These have to be fixed in time if we decide to merge this PR. Otherwise starting Mixxx with development settings in master becomes annoying.

I assume that these assertions do not appear in 2.3 if you tested it. No need to recompile everything twice locally. But we need to have a plan how to fix those in master.

@uklotzde
Copy link
Copy Markdown
Contributor

@daschuer Merge?

@Holzhaus
Copy link
Copy Markdown
Member Author

Let me recheck this first, I'll make sure that none of the assertions from master are already present here. I could be that these assertions just don't fire because skin is not lacking a CO.

Comment thread src/control/control.h Outdated
Comment thread src/mixer/playermanager.cpp Outdated
Comment thread src/mixer/playermanager.cpp Outdated
Comment thread src/control/control.h Outdated
@daschuer
Copy link
Copy Markdown
Member

daschuer commented Jul 1, 2020

The flaky test strikes again:

        Start  19: AutoDJProcessorTest.EnabledSuccess_DecksStopped_TrackLoadFails
 18/616 Test  #19: AutoDJProcessorTest.EnabledSuccess_DecksStopped_TrackLoadFails ..................***Failed    0.06 sec
qt.qpa.screen: QXcbConnection: Could not connect to display :99.0
Could not connect to any X display. 

can't we call mixxx-test instead of ctest?

@daschuer
Copy link
Copy Markdown
Member

daschuer commented Jul 1, 2020

The rest LGTM, Thank you.

@Holzhaus
Copy link
Copy Markdown
Member Author

Holzhaus commented Jul 1, 2020

The NoWarnIfMissing flag is only used for the legacy skin parser that uses getControl to check if a CO already exists. We could drop it by adding a ControlObject::exists(key) or ControlObject::getOrCreateControl(key) function. Should I do that? If so, what do you prefer?

@daschuer
Copy link
Copy Markdown
Member

daschuer commented Jul 2, 2020

Yes ControlObject::getOrCreateControl(key) would be much better express the intent.
I would prefer this, because it will require only one hash lookup.

@daschuer
Copy link
Copy Markdown
Member

daschuer commented Jul 2, 2020

Oh sorry, scratch that.

I am fine with the current solution. It is performs good and is easy to understand.

@Holzhaus
Copy link
Copy Markdown
Member Author

Holzhaus commented Jul 2, 2020

Ok, then it's ready to merge now.

@daschuer
Copy link
Copy Markdown
Member

daschuer commented Jul 2, 2020

Thank you for taking care if this.

@daschuer daschuer merged commit 98e95a5 into mixxxdj:2.3 Jul 2, 2020
@uklotzde
Copy link
Copy Markdown
Contributor

uklotzde commented Jul 3, 2020

After merging 2.3 into master many tests trigger debug assertions:

Example:

ControlDoublePrivate::getControl returning NULL for ( "[Master]" , "num_decks" )
DEBUG ASSERT: "flags.testFlag(ControlFlag::NoAssertIfMissing)" in function static QSharedPointer<ControlDoublePrivate> ControlDoublePrivate::getControl(const ConfigKey&, ControlFlags, ControlObject*, bool, bool, bool, double) at /tmp/mixxx/src/control/control.cpp:144
DEBUG ASSERT: "m_pControl || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:35
DEBUG ASSERT: "valid() || flags.testFlag(ControlFlag::NoAssertIfMissing)" in function void ControlProxy::initialize(ControlFlags) at /tmp/mixxx/src/control/controlproxy.cpp:36
a

@Holzhaus
Copy link
Copy Markdown
Member Author

Holzhaus commented Jul 4, 2020

See #2910.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants