how abort a execution of script lua ?

290 views
Skip to first unread message

Denis Dos Santos Silva

unread,
Jun 6, 2024, 5:52:27 PM6/6/24
to lua-l
Hi all!
looking lua documentation can't found a function to "abort execution of script".

question: it's possible abort (with throw a error) function ?

NOTE: lua os.exit() call c exit()

--- example
init c/app
init vm
load/run script (long running)
 abort execution (disk full or network failure) with flag of interrupt script
load/run another script
--- example

kind regards,

Sean Conner

unread,
Jun 6, 2024, 6:41:54 PM6/6/24
to lu...@googlegroups.com
It was thus said that the Great Denis Dos Santos Silva once stated:
> Hi all!
> looking lua documentation can't found a function to "abort execution of
> script".
>
> question: it's possible abort (with throw a error) function ?
>
> *NOTE: lua os.exit() call c exit()*
>
> --- example
> init c/app
> init vm
> load/run script (long running)
> abort execution (disk full or network failure) with flag of interrupt
> script
> load/run another script
> --- example

Calling os.exit() with a non-zero parameter is generally how it's done,
even in the C world where a program needs to indicate it stopped for some
error condition. The shell script can then check the value returned and do
something based on the value.

-spc

Denis Dos Santos Silva

unread,
Jun 6, 2024, 7:59:15 PM6/6/24
to lua-l
the issue with calling os.exit() call exit() then abort c/host application

maybe so like __halt_compiler() of php
https://www.php.net/manual/en/function.halt-compiler.php

Sean Conner

unread,
Jun 6, 2024, 9:18:00 PM6/6/24
to lu...@googlegroups.com
It was thus said that the Great Denis Dos Santos Silva once stated:
> the issue with calling os.exit() call exit() then abort c/host application
>
> maybe so like __halt_compiler() of php
> https://www.php.net/manual/en/function.halt-compiler.php

The example you gave:

> > > --- example
> > > init c/app
> > > init vm
> > > load/run script (long running)
> > > abort execution (disk full or network failure) with flag of interrupt
> > > script
> > > load/run another script
> > > --- example

appeared to me as a shell script, but otherwise, it wasn't clear what you
meant by "abort execution of the script."

Perhaps the Lua function error() works? Here's what the Lua manual says
about it (https://www.lua.org/manual/5.4/manual.html#pdf-error):

error (message [, level])

Raises an error (see §2.3) with message as the error object. This
function never returns.

Usually, error adds some information about the error position at the
beginning of the message, if the message is a string. The level
argument specifies how to get the error position. With level 1 (the
default), the error position is where the error function was called.
Level 2 points the error to where the function that called error was
called; and so on. Passing a level 0 avoids the addition of error
position information to the message.

You can "catch" the error with pcall() (and with lua_pcall() with the C
API).

-spc

Sainan

unread,
Jun 7, 2024, 1:53:53 AM6/7/24
to lu...@googlegroups.com
PHP's __halt_compiler kills the parser, not the VM.

An embedded environment would be wise to replace or remove os.exit. For example, an embedded environment in a game may use a coroutine-based scheduler that is ticked each game tick; in that case, you would simply clear the table of coroutines.

Thijs Schreijer

unread,
Jun 7, 2024, 3:55:38 AM6/7/24
to lu...@googlegroups.com
> Perhaps the Lua function error() works? Here's what the Lua manual says
> about it (https://www.lua.org/manual/5.4/manual.html#pdf-error):
>
> error (message [, level])
>
> Raises an error (see §2.3) with message as the error object. This
> function never returns.
>
> Usually, error adds some information about the error position at the
> beginning of the message, if the message is a string. The level
> argument specifies how to get the error position. With level 1 (the
> default), the error position is where the error function was called.
> Level 2 points the error to where the function that called error was
> called; and so on. Passing a level 0 avoids the addition of error
> position information to the message.
>
> You can "catch" the error with pcall() (and with lua_pcall() with the C
> API).
>
> -spc
>

The Lua code running might also have pcall to catch any error thrown, and then your pcall will not get it. In corowatch[1] I had this issue. So after a coroutine is set to be terminated, it updates the debughook to run every 1 instruction (is far lower during normal operation for performance reasons). On each instruction it will throw the error again, and again, and again... this will ensure you bypass all pcalls until the coroutine finally dies.

Thijs

[1] https://github.com/Tieske/corowatch/blob/43f7d7075de72a97474332a68d878daa801c5df8/src/corowatch.lua#L90-L91

Denis Dos Santos Silva

unread,
Jun 7, 2024, 2:02:06 PM6/7/24
to lua-l
Thanks everyone for the tips.

Tom Sutcliffe

unread,
Jul 8, 2024, 9:31:33 AM7/8/24
to lua-l
Setting the debughook to run every instruction and throwing an error from the hook is a trick I've used too, to impose a runtime limit on user-supplied code. First set a hook on X instructions (where X is your runtime limit), when that expires set a new hook every 1 instruction, in both cases throw an error at the end of the hook. As Thijs explained, the one-instruction hook ensures that even if code tries to pcall the first error, it can't run enough code to catch the next hook error (assuming no C code in the mix, since the instruction hook doesn't affect native code).

It was a while ago but I tried a lot of combinations of ways to try and beat that hook (short of unsetting it, obviously - the env I was using didn't expose the debug table), and I don't recall finding a situation that allowed you to bypass it. A tight loop calling an expensive C function could probably skew things pretty badly though. And if using coroutines you have to be sure to propagate debughooks between them since they are not inherited automatically.

Cheers,

Tom
> --
> You received this message because you are subscribed to the Google Groups "lua-l" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/lua-l/0571fe02-bf9c-45ba-8da6-eb7eeacad716%40app.fastmail.com.

Sainan

unread,
Jul 8, 2024, 10:55:28 AM7/8/24
to lu...@googlegroups.com
Try this: coroutine.resume(coroutine.create(function() while true do end end))

Tom Sutcliffe

unread,
Jul 8, 2024, 11:54:15 AM7/8/24
to lua-l
Well, as I said you do have to ensure your hook is set inside any coroutines you execute, so yes that example wouldn't work as written. But `while true do end` does increment the VM instruction count (or decrement the limit; I forget how it's implemented) each time through the loop so the technique does work - providing you have some way of ensuring coroutines are set up appropriately. When I've used it in the past to limit execution time, it's been in an environment that's already sandboxed to prevent uncontrolled access to the coroutine table (and debug, and os, etc), with some controlled access to coroutines provided by some C helper fns, which make sure to propagate the hook if necessary.

Cheers,

Tom

> On 8 Jul 2024, at 15:55, 'Sainan' via lua-l <lu...@googlegroups.com> wrote:
>
> Try this: coroutine.resume(coroutine.create(function() while true do end end))
>
> --
> You received this message because you are subscribed to the Google Groups "lua-l" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/lua-l/tN2pOr70GiKgUgtDeI8jL5XqzymUn7YqElmZLodHj55XQMkxszVnlt9GQkoAslMFoDOI70ORX8bfljrnJiRidYdMSTACP9W7lwgK00hbEdI%3D%40calamity.gg.

Thijs Schreijer

unread,
Jul 9, 2024, 10:52:06 AM7/9/24
to lu...@googlegroups.com
>>
>> Try this: coroutine.resume(coroutine.create(function() while true do end end))
>>

As Tom mentioned, you need to set up the env before use, corowatch provides patched versions for that like this one: https://github.com/Tieske/corowatch/blob/43f7d7075de72a97474332a68d878daa801c5df8/src/corowatch.lua#L192-L202

If the parent coro is watched, so is the child.

Thijs

bil til

unread,
Jul 10, 2024, 3:53:27 AM7/10/24
to lu...@googlegroups.com
Am Mo., 8. Juli 2024 um 17:54 Uhr schrieb 'Tom Sutcliffe' via lua-l
<lu...@googlegroups.com>:
>
> Well, as I said you do have to ensure your hook is set inside any coroutines you execute, so yes that example wouldn't work as written.

... to give you I reasonable answer, it would be nice to get a bit
more info about your application:
- running in an OS? ("standard" OS like Linux or Windows or anything
more special? Or embedded on some microcontroller?
- extensive use of coroutines?
- problems with EVERY exit, or only if some special coroutines are
currently active?
Reply all
Reply to author
Forward
0 new messages