|
|
|
05-26-2017, 06:30 PM
|
#1
|
Banned
Join Date: Nov 2015
Posts: 406
|
Lua terminate script immediately
I have the need to terminate a script immediately whens something goes wrong yet none of the methods work:
reaper.atexit(exit) with exit calling gfx.exit()(some somewhere on this site, I think exit is just a callback when the script terminates normally, so this is useless).
os.exit, shell.exit: neither os nor shell are defined.
|
|
|
05-26-2017, 07:16 PM
|
#2
|
Human being with feelings
Join Date: Mar 2016
Posts: 117
|
Hi!
that may good working with use "label" of lua. ( Goto Statement )
document : lua-users.org ( http://lua-users.org/wiki/GotoStatement )
Code:
local count = 0;
while( true)
do
if ( count > 20)
then
goto exit; -- when timing of want to finish script.
end
reaper.ShowConsoleMsg(tostring(count) .. "\n");
count = count +1;
end
-- label at last line
::exit::
thanks!
|
|
|
05-26-2017, 07:19 PM
|
#3
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 4,968
|
Another way is to use a return statement preventing further instructions in the current function (or global) from executing.
Code:
function someFunctionThatMayFail()
if success then
return true
else
return false
end
if not success then
reaper.ShowConsoleMsg("Error 234: Violin is badly tuned.")
return
end
if not someFunctionThatMayFail()
reaper.ShowConsoleMsg("Error 432: Tempo has gone offline.")
return
end
|
|
|
05-26-2017, 07:30 PM
|
#4
|
Human being with feelings
Join Date: Mar 2016
Posts: 117
|
"return" ! nice work it.
|
|
|
05-26-2017, 09:29 PM
|
#5
|
Banned
Join Date: Nov 2015
Posts: 406
|
None of these are solutions. They do not work in general. I need a direct way to exit at any point in code.
I have a global error handler that does nifty stuff and when it is called to do it's thing, it needs to exit, else reaper continues executing code and runs in to a problem and then throws an error in a modal dialog box(which is redundant because I already showed more error info than reaper's error handler). I simply need my error handler to have a way to terminate the script directly.
1. labels don't work because you can't escape to different scopes. Since my error function is in a function I can't use goto in it to call escape. Proof: That was one of the first things I tried and lua say that the label did not exist.(though it did, just outside the scope of the function).
2. return don't work because it would require every function that is called to return if any function it called had an error. This would be extremely noisy in the source, would obfuscate function returns, and would be very error prone.
Both have the same problem, I can't use it them in functions. Both simply exit the current scope. I need to exit the global scope(terminate the script).
|
|
|
05-26-2017, 11:19 PM
|
#6
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 4,968
|
Quote:
Originally Posted by Airal
2. return don't work because it would require every function that is called to return if any function it called had an error. This would be extremely noisy in the source, would obfuscate function returns, and would be very error prone.
|
This is pretty much how well-written C code works.
Yet another way to (not cleanly) abort the execution of a Lua program is the assert function. The diagnostic message it displays can be silenced using Lua's protected execution mode.
Last edited by cfillion; 05-27-2017 at 01:46 AM.
|
|
|
05-27-2017, 01:29 AM
|
#7
|
Banned
Join Date: Nov 2015
Posts: 406
|
Quote:
Originally Posted by cfillion
This is pretty much how well-written C code works.
Yet another way to (not cleanly) abort the execution of a Lua program is the assert function. The diagnostic message it displays can be silenced using Lua's protected execution mode.
|
Fortunately I don't program in C. I tried assert and it does work but still an error(the assert error). I tried wrapping that in a pcall and it does nothing(ignores the assert completely)(I assume that is what you meant, more or less?).
So, the assert is better than nothing but I'd still like to get rid of the error display from reaper and use my own.
|
|
|
05-27-2017, 01:48 AM
|
#8
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 4,968
|
Example using the error function to pass around a more useful message than assert does:
Code:
local SCRIPT_NAME = ({reaper.get_action_context()})[2]:match('([^/\\_]+).lua$')
local MB_OK = 0
local ok, err = pcall(function()
reaper.ShowConsoleMsg("abc\n")
error({message="Lights are out in the quantum tunnel"})
reaper.ShowConsoleMsg("def\n") -- this instruction will not run
end)
if not ok then
local body = string.format('The following error occurred: "%s".', err.message)
reaper.MB(body, SCRIPT_NAME, MB_OK)
end
Last edited by cfillion; 05-27-2017 at 02:03 AM.
|
|
|
05-27-2017, 10:43 AM
|
#9
|
Banned
Join Date: Nov 2015
Posts: 406
|
This doesn't terminate the script and I still get reapers original error box about the original error in the program. So it actually makes it worse because I end up with two error boxes.
I simply want to terminate a script immediately with no error boxes popping up(reapers or otherwise(as I can add my own))... ;/ It shouldn't be that hard ;/
|
|
|
05-27-2017, 12:12 PM
|
#10
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 4,968
|
Have you tried with the same code? Here abc is displayed in the console and the custom error is displayed in the message box. The normal Lua error message and def aren't shown.
|
|
|
05-27-2017, 01:07 PM
|
#11
|
Banned
Join Date: Nov 2015
Posts: 406
|
Quote:
Originally Posted by cfillion
Have you tried with the same code? Here abc is displayed in the console and the custom error is displayed in the message box. The normal Lua error message and def aren't shown.
|
Yes, I copied and pasted your code.
I think the problem is, is that your code doesn't actually throw an error anywhere! So it just passes through without triggering the internal error handler of reaper.
Try calling a reaper command with an invalid argument that would normally cause reaper to pop up a script error.
Put it as the last command to be called in your script. It should be called(cause your script doesn't terminate after you post your error box. Try using os.exit(), assert, etc(which none work as desired, the only point of the original post)).
Then you should see the problem.
|
|
|
05-27-2017, 01:15 PM
|
#12
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 4,968
|
You can do something like this to restore the default behavior of Lua errors:
Code:
local SCRIPT_NAME = ({reaper.get_action_context()})[2]:match('([^/\\_]+).lua$')
local MB_OK = 0
function main()
-- all of the script code here
reaper.hello_world()
--error({message="custom error"})
-- this line won't run if there has been an error above
end
local ok, err = pcall(main)
-- anything here after pcall will continue running after an error
if not ok then
if type(err) == 'table' and err.message then
-- handle a custom error
local body = string.format('The following error occurred: "%s".', err.message)
reaper.MB(body, SCRIPT_NAME, MB_OK)
else
-- handle a standard Lua error
error(err, 2)
end
end
Last edited by cfillion; 05-27-2017 at 01:27 PM.
|
|
|
05-27-2017, 01:30 PM
|
#13
|
Human being with feelings
Join Date: Jun 2012
Location: Spain
Posts: 7,268
|
Airal,
calling gfx.quit() should work to terminate the script at any point
|
|
|
05-27-2017, 02:47 PM
|
#14
|
Banned
Join Date: Nov 2015
Posts: 406
|
Heda: It doesn't, that was another thing I tried.
if I do
gfx.quit();
assert(nil, "error");
I get the assert.
Possibly it requires actually creating some graphical window for it to work?
If I try
gfx.init("", 200, 200, 1)
gfx.quit();
at the top of my program, it still runs so gfx.quit() is not ending the script.
e.g.,
gfx.init("Test", 200, 200);
reaper.ShowConsoleMsg("asdfasdf");
gfx.quit();
reaper.ShowConsoleMsg("1234324");
gfx.quit simply closes the gfx window, it does not terminate the script.
Any other ideas?
|
|
|
05-27-2017, 03:39 PM
|
#15
|
Human being with feelings
Join Date: Jun 2012
Location: Spain
Posts: 7,268
|
ok I've read more carefully in further replies now... sorry.
I think solutions given by kawa and cfillion are good
Maybe you are overcomplicating things.
Rethink your structure of functions. if you need to exit, you can use a flag variable, and in the next loop or whatever you do, just don't loop if the flag is set. Then the flow will continue after the loop and reach the end and exit naturally. I think I can't help more if no example code or specific function is given.
|
|
|
05-27-2017, 03:53 PM
|
#16
|
Banned
Join Date: Nov 2015
Posts: 406
|
Quote:
Originally Posted by heda
ok I've read more carefully in further replies now... sorry.
I think solutions given by kawa and cfillion are good
Maybe you are overcomplicating things.
Rethink your structure of functions. if you need to exit, you can use a flag variable, and in the next loop or whatever you do, just don't loop if the flag is set. Then the flow will continue after the loop and reach the end and exit naturally. I think I can't help more if no example code or specific function is given.
|
No, you don't understand. 1st. You can't say someone elses solution is good when it doesn't work(of course, you can but then that makes you wrong). 2. You can't tell me I should rewrite my entire program and make it more bloated because of missing functionality that almost all languages have.
It's much simpler to say "Ok, we need a viable method to terminate the script(or in generate, our current ideas about things are inadequate and we need to improve them) and then add that functionality instead of needless and inane work arounds. Else, with that kinda logic, we might as well go back to using the abacus.
|
|
|
05-27-2017, 03:57 PM
|
#17
|
Banned
Join Date: Sep 2015
Posts: 1,650
|
You could execute your script as a coroutine so you can yield anywhere and not do anything if yielded...
Code:
local function DBG(str)
reaper.ShowConsoleMsg(tostring(str) .. "\n")
end
local function isError(case)
if case then coroutine.yield(-1) end
DBG("Hasn't stopped")
end
local function myCoolScript()
DBG("This is a very cool script")
isError(true)
DBG("Continuing...")
end
local function main()
local co = coroutine.create(
function ()
myCoolScript()
DBG("Continuing from main coroutine")
end
)
coroutine.resume(co)
if coroutine.status(co) ~= "suspended" then reaper.defer(main) end
end
main()
|
|
|
05-27-2017, 04:23 PM
|
#18
|
Banned
Join Date: Nov 2015
Posts: 406
|
Quote:
Originally Posted by snooks
You could execute your script as a coroutine so you can yield anywhere and not do anything if yielded...
Code:
local function DBG(str)
reaper.ShowConsoleMsg(tostring(str) .. "\n")
end
local function isError(case)
if case then coroutine.yield(-1) end
DBG("Hasn't stopped")
end
local function myCoolScript()
DBG("This is a very cool script")
isError(true)
DBG("Continuing...")
end
local function main()
local co = coroutine.create(
function ()
myCoolScript()
DBG("Continuing from main coroutine")
end
)
coroutine.resume(co)
if coroutine.status(co) ~= "suspended" then reaper.defer(main) end
end
main()
|
Thanks! You win the prize! First working solution and somewhat out of the box thinking! I'd give you a gold star if I had one! While I have to integrate it in to my code, and requiring a wrapper around main is a slight hindrance(since I'm trying to do this in library code).
Unfortunately, I'm gonna have to take that gold star away and give a silver star instead! The code doesn't work across modules so I can't wrap up all the overhead in a library solution because the library can't call the main function to start the program.
I was able to hack this though, So I'll give you a gold star with one point removed!
require "library"
main = function()
...
end
require "libraryhack"
Here libraryhack effectively has your code in in it and it can see main while library can't(for some reason, even though main is global).
But now my error handling code doesn't display the call stack correctly for some reason ;/ This might be fixable but I'll have to investigate some(seems that coroutines screw up debug.getinfo). All this trouble simply because we don't have a single function that actually can terminate a script ;/ amazing... It's like preparing a huge and expensive feat and forgetting the forks.
Last edited by Airal; 05-27-2017 at 04:28 PM.
|
|
|
05-27-2017, 04:57 PM
|
#19
|
Banned
Join Date: Nov 2015
Posts: 406
|
The solution seems to be to wrap the main entry point with xpcall. This creates a custom error that can handle any of the errors and prevents reapers error(since xpcall intercepts the error).
It still requires me to use the "libraryhack" to access main which is an undesirable due requiring a main and an extra require.
Last edited by Airal; 05-27-2017 at 06:51 PM.
|
|
|
08-23-2022, 12:05 AM
|
#20
|
Human being with feelings
Join Date: Apr 2022
Posts: 1
|
To those of you after seeing this thread in the future.
You are all aware of the addition in REAPER 6.29 of the ReaScriptError() function's ! prefix, which allows you to stop the script at any time. (It is also described in the current API documentation)
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 12:41 AM.
|