It is currently September 8th, 2024, 2:46 am

[Bug] Why does this nested inline Lua function crash Rainmeter only when used in MeterStyle?

Report bugs with the Rainmeter application and suggest features.
Crest
Posts: 148
Joined: August 16th, 2013, 12:47 pm

[Bug] Why does this nested inline Lua function crash Rainmeter only when used in MeterStyle?

Post by Crest »

I have a function that compares two argument values, and returns a third arg if true otherwise returning an forth arg.

The first arg passed to this function is itself a separate inline function that checks the `#CURRENTSECTION#` for the presence of an option, returning it if found.

I'm using this for the MeterStyle to conditionally add another style if a condition is met, inline rather than relying on a peripheral measure or meter-specific handling via Lua.

The line looks like the following:

Code: Select all

MeterStyle=SomeStyle | AnotherStyle [&Sc:Repl('[&Sc:Chk('#CURRENTSECTION#','SomeOption')]','MyVal','| YetAnotherStyle','')]
This crashes Rainmeter (edit: on 4.5.17, just noticed there's a .18 out, edit 2: crashes with it, too). However if the same function line is used for say a `Text` option value it works as expected. I've tried changing the inner nested function to double quotes as a test but no difference.

Alternatively if I replace the inner nested `Chk` function with some other function that doesn't use `SKIN:GetMeter()` and `GetOption()` and instead just returns some static arg back then it doesn't crash.

Is this some inherent limitation of using `SKIN` bangs within a function within MeterStyle or just a bug?
User avatar
Yincognito
Rainmeter Sage
Posts: 8030
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Why does this nested inline Lua function crash Rainmeter only when used in MeterStyle?

Post by Yincognito »

Can you post a simplified code sample exhibiting the issue? My guess that it's either an internal endless loop somewhere, or the fact that you're trying to get the options of a meter from an option (the meter style) that's actively building / importing the options of that meter in the first place (e.g. something akin to self referencing), if it makes sense. :???:

In the meantime, I'll try replicating the scenario based on your details, and see if I get the crash too.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
Crest
Posts: 148
Joined: August 16th, 2013, 12:47 pm

Re: Why does this nested inline Lua function crash Rainmeter only when used in MeterStyle?

Post by Crest »

Simple test case:

INI (in this state it's just showing the identical inline function working in a Text string, to see crashing behavior comment out the normal `MeterStyle` and enable the second one below it)

Code: Select all

[Variables]
C1=58,188,109
C2=209,82,79

[Rainmeter]
AccurateText=1
DynamicWindowSize=1
Update=1000

[Sc]
Measure=Script
ScriptFile=Script.lua

[SomeStyle]
X=0
Y=0
DynamicVariables=1

[AnotherStyle]
W=200
H=100
FontColor=#C1#

[YetAnotherStyle]
FontColor=#C2#

[Example]
Meter=String
MeterStyle=SomeStyle | AnotherStyle | YetAnotherStyle
; MeterStyle=SomeStyle | AnotherStyle [&Sc:Repl('[&Sc:Chk('#CURRENTSECTION#','SomeOption')]','MyVal','| YetAnotherStyle')]
SomeOption=MyVal
Text=[&Sc:Repl('[&Sc:Chk('#CURRENTSECTION#','SomeOption')]','MyVal','| YetAnotherStyle')]
SolidColor=0,0,0
Script

Code: Select all

function Initialize()
end

function Repl(in1,in2,ret)
    if in1 == in2 then
        return ret
    else
        return ""
    end
end

function Chk(name,op)
    local m = SKIN:GetMeter(name)
    local o = m:GetOption(op,'',false)
    if o then
        return o
    else
        return 0
    end
end
The Lua itself doesn't have an endless loop but internally perhaps yeah I'm guessing like you mentioned it may be something self-referencing.

The workaround is having to define the base MeterStyles as a variable then using a measure to conditionally add to/restore from but would have been neater to have it work inline, since it works for other scenarios.
User avatar
Brian
Developer
Posts: 2725
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: Why does this nested inline Lua function crash Rainmeter only when used in MeterStyle?

Post by Brian »

This is definitely a bug....but fixing it will be somewhat complicated (if it is even possible).

What is happening is while the meter is first setting up, it calls a custom lua function (from your MeterStyle). This function in turn calls the same meter's GetOption function, which in turns parses the MeterStyle of the same meter.....which in turn calls the lua script again....and again and again.

Basically an endless loop is happening and the program runs out of stack space and crashes.

Honestly, I have no idea if this is possible to fix since it involves a form of self-referencing. It might only effect the MeterStyle option, but I am not sure about that.

For now you may have to go with your workaround.

-Brian

PS - It's a good idea to use different quotes when nesting quoted items.
Example:
Original version: [&Sc:Repl('[&Sc:Chk('#CURRENTSECTION#','SomeOption')]','MyVal','| YetAnotherStyle')]
Better version: [&Sc:Repl("[&Sc:Chk('#CURRENTSECTION#','SomeOption')]",'MyVal','| YetAnotherStyle')]
User avatar
Yincognito
Rainmeter Sage
Posts: 8030
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Why does this nested inline Lua function crash Rainmeter only when used in MeterStyle?

Post by Yincognito »

Brian wrote: June 3rd, 2024, 5:45 am What is happening is while the meter is first setting up, it calls a custom lua function (from your MeterStyle). This function in turn calls the same meter's GetOption function, which in turns parses the MeterStyle of the same meter.....which in turn calls the lua script again....and again and again.
[...]
It might only effect the MeterStyle option, but I am not sure about that.
Well, based on the report and the code (didn't have the time to test the latter or find other possible workarounds yet, but will do once I get the chance), it works just fine if placed in the Text option, even though it's more or less the same internal process / loop.

This is why I originally thought it might have something to do with the meter style "actively building / importing the options of that meter", something that also can potentially change the structure of the referenced meter, e.g. the number of options in it (directly affecting GetOption() and its own internal FOR / WHILE loop in the process). Most of the other options besides MeterStyle (including the Text option) don't do the latter, sticking with changing only their own contents and sometimes the contents of other options, and this (or the timing of various options) might explain why it works when the Lua function is called from them. Just a supposition, of course, you know best the internal particularities of the Rainmeter code.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth