On Tue, May 11, 2021 at 05:41:28PM -0300, Joao Morais wrote:
> 
> 
> > Em 10 de mai. de 2021, à(s) 18:04, Willy Tarreau <w...@1wt.eu> escreveu:
> > 
> > On Mon, May 10, 2021 at 10:41:36PM +0200, Willy Tarreau wrote:
> >>> core.register_action("auth", { "http-req" }, function(txn)
> >>>   txn:set_var("txn.code", 401, true)
> >                                     ^^^^
> > So the problem is exactly here and it works as designed. This
> > argument "ifexist" was added a year ago to avoid Lua allocating
> > random variable names:
> > 
> >  4e172c93f ("MEDIUM: lua: Add `ifexist` parameter to `set_var`")
> > 
> > What the "true" argument does here is to refrain from creating
> > the variable if it does not exist. After you look it up from the
> > service, the variable gets created and it exists, hence why it
> > then works next times.
> > 
> > If you want it to always be created (which I assume you want
> > to), just drop this argument or explicitly set it to false.
> 
> Thanks Willy for the explanation and sorry about the false alarm, I didn't
> see the whole picture here.

No problem, it made me search and (re)discover this area :-)

> Just to confirm how it works, I created the snippet below:
> 
>     http-request lua.auth ## assigning txn.core
>     http-request return lf-string %[var(txn.code)] content-type text/plain
> 
> It worked since the first run and this is the only place I declared txn.code.
> Does this mean that a var is created in the following conditions?
> Any change in the sentences below?
> 
> - after the first read from a  Lua script
> - after the first write from a Lua script provided that ifexists parameter is 
> set to false
> - always exists, if used anywhere in the configuration file

It's not a matter of first or second access. It's that the function
you used initially resulted in always allocating an entry for the
variable's name, causing some huge memory usage for those who were
using them like maps and performing random lookups there. In order
to avoid this, Tim added an extra argument saying that we're just
performing an opportunistic lookup and that the variable must not
be created if it does not exist.

Other parts of the code (the native config parts I mean) which use
variables always result in a creation because these names are static.
So my understanding is that it can be simplified to this:
  - a variable declared in the config always exists
  - a variable accessed from Lua with ifexists set to true will not
    be created but will be found if it exists
  - a vraiable accessed from Lua with ifexists set to false or not
    present will always be created during the lookup.

Interestingly, the code for variables was initially made for the config,
so it doesn't seem to destroy variable names when they're released since
that was pointless with the config. I think that code should be revisited
in 2.5 to improve the situation (e.g. by marking that the variable was
dynamically allocated maybe), but I don't know this part well so I'll
probably stop before starting to suggest stupidities :-)

Willy

Reply via email to