Lua state lifetime

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Lua state lifetime

Fotis Panagiotopoulos

I am using Lua in a microcontroller environment, and recently I had some crashes related to corruption of the heap data.

The issue was tracked down to be the following sequence:

  1. Call to lua_pcall(L, 0, 0, 0) without checking the return value.
  2. Call to another function, again with lua_pcall(L, 0, 0, 0), this time checking the return value.
  3. Step 2 fails (as in fact step 1 had failed, but I didn't catch it), and calls lua_close(L);
  4. During lua_close(L) memory is deallocated. At this stage the memory manager detects a corruption to the heap, and the firmware crashes.

I would like to ask, at which cases can a Lua state be invalid? (And thus no other operations are allowed).

  • Is it always safe to call lua_close()?
  • If a lua_pcall() fails, is it allowed to use again lua_pcall() calling another function?
  • In case lua_pcall() fails with "not enough memory", can any assumptions be made about the memory state? Can lua_close() be called then, or generally any other Lua API function?
Reply | Threaded
Open this post in threaded view
|

Re: Lua state lifetime

Ką Mykolas
Could You please provide a little bit more details on the environment You'e working on? Is it eLua by any chance? Which kind of controller are we talking about?

On Wed, 10 Apr 2019, 12:02 Fotis Panagiotopoulos, <[hidden email]> wrote:

I am using Lua in a microcontroller environment, and recently I had some crashes related to corruption of the heap data.

The issue was tracked down to be the following sequence:

  1. Call to lua_pcall(L, 0, 0, 0) without checking the return value.
  2. Call to another function, again with lua_pcall(L, 0, 0, 0), this time checking the return value.
  3. Step 2 fails (as in fact step 1 had failed, but I didn't catch it), and calls lua_close(L);
  4. During lua_close(L) memory is deallocated. At this stage the memory manager detects a corruption to the heap, and the firmware crashes.

I would like to ask, at which cases can a Lua state be invalid? (And thus no other operations are allowed).

  • Is it always safe to call lua_close()?
  • If a lua_pcall() fails, is it allowed to use again lua_pcall() calling another function?
  • In case lua_pcall() fails with "not enough memory", can any assumptions be made about the memory state? Can lua_close() be called then, or generally any other Lua API function?
Reply | Threaded
Open this post in threaded view
|

Re: Lua state lifetime

Fotis Panagiotopoulos
I am using Lua 5.2.2.
It is running on an STM32F427VIT6 MCU. It is not eLua, the environment is wirtten from scratch (including the memory manager that I am using). I am using the official Lua code, with the only modification being the LTR patch as discribed be the eLua project.

At the moment, based on the latest tests I am quite confident that the problem is reproducible only when lua_pcall(L, 0, 0, 0) returns with a not enout memory. It seems that other errors do not trigger this problem. Ia have also checked that atpanic is never called.

Στις Τετ, 10 Απρ 2019 στις 12:40 μ.μ., ο/η Ką Mykolas <[hidden email]> έγραψε:
Could You please provide a little bit more details on the environment You'e working on? Is it eLua by any chance? Which kind of controller are we talking about?

On Wed, 10 Apr 2019, 12:02 Fotis Panagiotopoulos, <[hidden email]> wrote:

I am using Lua in a microcontroller environment, and recently I had some crashes related to corruption of the heap data.

The issue was tracked down to be the following sequence:

  1. Call to lua_pcall(L, 0, 0, 0) without checking the return value.
  2. Call to another function, again with lua_pcall(L, 0, 0, 0), this time checking the return value.
  3. Step 2 fails (as in fact step 1 had failed, but I didn't catch it), and calls lua_close(L);
  4. During lua_close(L) memory is deallocated. At this stage the memory manager detects a corruption to the heap, and the firmware crashes.

I would like to ask, at which cases can a Lua state be invalid? (And thus no other operations are allowed).

  • Is it always safe to call lua_close()?
  • If a lua_pcall() fails, is it allowed to use again lua_pcall() calling another function?
  • In case lua_pcall() fails with "not enough memory", can any assumptions be made about the memory state? Can lua_close() be called then, or generally any other Lua API function?
Reply | Threaded
Open this post in threaded view
|

Re: Lua state lifetime

Luiz Henrique de Figueiredo
> I am using Lua 5.2.2.

I suggest you upgrade to Lua 5.2.4, which is the last release of Lua
5.2. I'm not sure it'll fix your issue but it'll be one less thing to
check.

Reply | Threaded
Open this post in threaded view
|

Re: Lua state lifetime

Fotis Panagiotopoulos
Well... Changing Lua version at this stage of the project is quite difficult.
It is very possible that there is a bug in my code and not in Lua, and in any case I have found my solution (check the return of the first pcall).

However I want to better understand how Lua works, hence the question.

According to the language spec, what are the cases that the Lua state may become undetermined/corrupt/broken/etc? Are there cases that I sould not call another function, or that calling lua_close is illegal?


Στις Τετ, 10 Απρ 2019 στις 2:57 μ.μ., ο/η Luiz Henrique de Figueiredo <[hidden email]> έγραψε:
> I am using Lua 5.2.2.

I suggest you upgrade to Lua 5.2.4, which is the last release of Lua
5.2. I'm not sure it'll fix your issue but it'll be one less thing to
check.

Reply | Threaded
Open this post in threaded view
|

Re: Lua state lifetime

Roberto Ierusalimschy
In reply to this post by Fotis Panagiotopoulos
> I would like to ask, at which cases can a Lua state be invalid? (And thus
> no other operations are allowed).
>
>    - Is it always safe to call lua_close()?

Yes.


>    - If a lua_pcall() fails, is it allowed to use again lua_pcall() calling
>    another function?

Yes. (By "fails" you mean returns an error code, right?)


>    - In case lua_pcall() fails with "not enough memory", can any
>    assumptions be made about the memory state? Can lua_close() be called
>    then, or generally any other Lua API function?

Yes. Bar unkown bugs, "not enough memory" should be like any other
error, and should leave Lua in a normal state.  Of course, due to its
nature, subsequent operations may fail too, while there is not enough
memory. However, critical paths like 'pcall' and 'lua_close' do not
allocate any memory and should work correctly even without any memory
left.

The standard tests include extensive tests around "not enough memory"
errors, using a special allocator that forces these errors. However,
in our experience, this is far from the norm in software practice.
Therefore, many other parts of a system (e.g., external libraries or
even libc) may not be as well behaved as Lua regarding this scenario.
(Of course, there may be bugs in Lua, too.)

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Lua state lifetime

Fotis Panagiotopoulos
Thank you!
The provided information helped me a lot.

Although I believe that this is not the case, I will also modify my memory allocator, to stop allocations when a specific limit is reached (e.g. 90% of total memory) to ensure stable operation of the rest of the system.

Στις Τετ, 10 Απρ 2019 στις 5:43 μ.μ., ο/η Roberto Ierusalimschy <[hidden email]> έγραψε:
> I would like to ask, at which cases can a Lua state be invalid? (And thus
> no other operations are allowed).
>
>    - Is it always safe to call lua_close()?

Yes.


>    - If a lua_pcall() fails, is it allowed to use again lua_pcall() calling
>    another function?

Yes. (By "fails" you mean returns an error code, right?)


>    - In case lua_pcall() fails with "not enough memory", can any
>    assumptions be made about the memory state? Can lua_close() be called
>    then, or generally any other Lua API function?

Yes. Bar unkown bugs, "not enough memory" should be like any other
error, and should leave Lua in a normal state.  Of course, due to its
nature, subsequent operations may fail too, while there is not enough
memory. However, critical paths like 'pcall' and 'lua_close' do not
allocate any memory and should work correctly even without any memory
left.

The standard tests include extensive tests around "not enough memory"
errors, using a special allocator that forces these errors. However,
in our experience, this is far from the norm in software practice.
Therefore, many other parts of a system (e.g., external libraries or
even libc) may not be as well behaved as Lua regarding this scenario.
(Of course, there may be bugs in Lua, too.)

-- Roberto