Ever noticed that if you open the interface options and then click cancel whilst in combat, everything blows up? It will throw taint errors and randomly blame any addon that has added a config panel to the Interface Options. This thread is about investigating this taint.
Maybe this rings a bell?
The story1x [ADDON_ACTION_BLOCKED] AddOn 'Skada' tried to call the protected function 'CompactRaidFrameContainer:Show()'.
The issue is with the InterfaceOptionsFrame_OnShow function.
function InterfaceOptionsFrame_OnShow (self) InterfaceCategoryList_Update(); [B]InterfaceAddOnsList_Update[/B](); -- Problematic if ( not InterfaceOptionsFramePanelContainer.displayedPanel ) then InterfaceOptionsFrame_OpenToCategory(CONTROLS_LABEL); end InterfaceOptionsOptionsFrame_RefreshCategories(); InterfaceOptionsOptionsFrame_RefreshAddOns(); endCurrently due to the order of these functions calls, the execution path becomes tainted after the call to InterfaceAddOnsList_Update.
This is a large function contained in InterfaceOptionsFrame.lua line 137.
This function ultimately goes on to call OptionsList_DisplayButton which is at line 84 of OptionsFrameTemplates.lua. Which changes the text of the button viewed in the Interface Options panel to yourAddonFrame.name which everyone taints when adding a config panel to the Interface Options.
button.text:SetText(element.name);Reproducing the issue with 0 addons
Run the following script >> get into combat (with a target dummy) >> open the interface options >> click cancel >> action blocked
/script local p=CreateFrame("Frame");p.name="Test";InterfaceOptions_AddCategory(p)Temporary solution
do local ufUpdate, abUpdate, abeUpdate local f = CreateFrame("Frame") local ufWrapper = CompactUnitFrameProfiles_CancelChanges CompactUnitFrameProfiles_CancelChanges = function(self) if not InCombatLockdown() then ufWrapper(self) else ufUpdate = self f:RegisterEvent("PLAYER_REGEN_ENABLED") end end local abWrapper = InterfaceOptions_UpdateMultiActionBars InterfaceOptions_UpdateMultiActionBars = function() if not InCombatLockdown() then abWrapper() else abUpdate = true f:RegisterEvent("PLAYER_REGEN_ENABLED") end end InterfaceOptionsActionBarsPanelBottomLeft.setFunc = InterfaceOptions_UpdateMultiActionBars InterfaceOptionsActionBarsPanelBottomRight.setFunc = InterfaceOptions_UpdateMultiActionBars InterfaceOptionsActionBarsPanelRight.setFunc = InterfaceOptions_UpdateMultiActionBars InterfaceOptionsActionBarsPanelRightTwo.setFunc = InterfaceOptions_UpdateMultiActionBars InterfaceOptionsActionBarsPanelLockActionBars.setFunc = InterfaceOptions_UpdateMultiActionBars local abeWrapper = InterfaceOptionsActionBarsPanelAlwaysShowActionBars.setFunc InterfaceOptionsActionBarsPanelAlwaysShowActionBars.setFunc = function() if not InCombatLockdown() then abeWrapper() else abeUpdate = true f:RegisterEvent("PLAYER_REGEN_ENABLED") end end f:SetScript("OnEvent", function(self) if ufUpdate then ufWrapper(ufUpdate) ufUpdate = nil end if abUpdate then abWrapper() abUpdate = nil end if abeUpdate then abeWrapper() abeUpdate = nil end self:UnregisterEvent("PLAYER_REGEN_ENABLED") end) endBreakdown on my solution
What does it do? This is basically the function that is registered to the "Raid Profiles" panel in the Interface Options to fire when the cancel button is pressed. All I'm doing is hooking said function, so that if the cancel button is pressed in combat, none of the changes are saved, until the user leaves combat. This is because the execution path is already tainted earlier, so we prevent this tainted execution path from trying to show/hide frames in combat, which results in taint errors.
The odds of someone making changes to the raid profiles in combat and then deciding to cancel them are low. Much lower than how frequently this taint issue is occurring.
I'm probably going to shove this into the LibChatAnims library. I know it's not exactly appropriately named, but it's an easy way to mass distribute a taint fix across the WoW playerbase. I should have probably just named it LibTaintFix in the first place, but it's really not that important.
Ideally Blizzard should fix this by re-arranging the order of the function calls in InterfaceOptionsFrame_OnShow to fire the Blizzard functions first, followed by the addon functions.