Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


pcall won't catch "is an invalid <type>" err

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
Estecka
How do I cheat?
Reputation: 0

Joined: 05 Mar 2022
Posts: 4
Location: France

PostPosted: Sat Mar 05, 2022 3:57 pm    Post subject: pcall won't catch "is an invalid <type>" err Reply with quote

Hi,

I was only recently introduced to lua, so I might be missing something obvious.

I was working on some boilerplate lua script loop.
Because I've often caused some dramatic looping errors before, I wanted to set up some kind of catch-all error handler, that would abort the loop if anything goes wrong :
Code:
function Update()
   -- Script logic will go here.
   print("Before error");
   AddressList["HP"].value = nil; -- Should throw an error.
   print("After error");
end

LuaLoop = createTimer();
LuaLoop.interval = 1000/60;
LuaLoop.Enabled = false;
LuaLoop.onTimer = function ()
   local ok, msg = pcall(Update);
   print("Ok:", (ok and 'true' or 'false'), "Msg:", msg);
   if (not ok) then
      LuaLoop.setEnabled(false);
      print("Lua Script Loop aborted");
   end
end



The error thrown in the script logic is `Error:"" is an invalid float`
I would expect pcall to catch this error, but the error passes right through it; nothing in the code after pcall is evaluated, as if pcall itself had thrown an error.
What can I do to catch this error properly ?

Eventually, if I don't manually abort the loop, the repeating error will cause a `C stack overflow`. This one is caught in pcall and aborts the loop as expected, but at this point it's already too late; the Lua Script Table is busted, and I need to completely restart Cheat Engine in order to use it again.

_________________
Y s'taient cachés les steaks hachés.
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sat Mar 05, 2022 5:44 pm    Post subject: Reply with quote

I'd say it's just due to different error handling with in CE's code. I don't think pcall is setup to catch all errors it's more for catching lua errors not C level stuff. I'd say focus more on proper error handling and not trying to use a catch all. So have checks to make sure the value is of the right type and throw an error if it's not.
_________________
Back to top
View user's profile Send private message Visit poster's website
Estecka
How do I cheat?
Reputation: 0

Joined: 05 Mar 2022
Posts: 4
Location: France

PostPosted: Sun Mar 06, 2022 1:06 pm    Post subject: Reply with quote

Sure, type-checking will fix the issue right here and right now in this specific script, but that's it, and that's not quite what I'm looking for.
Writing a script that doesn't fail is good, but walking out of this with the assumption I'll never again write a script that fails in the exact same way (or any other way for that matter) would be presumptuous of me. I need that catch-all handler not to "fix" the error, but as a fail-safe, because the consequences for failure here are quite spectacular, and I want to attenuate them.

Aside, I'm thinking that if the only way to throw a proper error, is to wrap all value assignation with some type checking, maybe this check would deserve to be built into the setter for `MemoryRecord.value` ?

Quote:
I don't think pcall is setup to catch all errors it's more for catching lua errors not C level stuff.

There's something I don't get here. Does "C stackoverflow" -the one error that is actually being caught here-, not count as a C level error ?
Conversely, "is an invalid float" is a runtime error I'd expect to come from Lua, not from a strong-typed low-level languages like C; pure C doesn't even have a mechanism for throwing this kind of errors as far as I know.

_________________
Y s'taient cachés les steaks hachés.
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 51

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Sun Mar 06, 2022 1:40 pm    Post subject: Reply with quote

When I said C level, I was making a generalisation. CE is written with pascal not Lua, thus when you set "SomeMemeoryRecord.Value" it's using pascal code to do that. It's just that the memory record object is exposed to lua.

And you can wrap an entire C# program in a try call, but any programmer worth their weight will tell you not to do anything like that and to work on proper error handling.

And it seems like the error is handled in pascal, that's why you get the invalid float error. But the pcall doesn't catch it and the timer keeps spamming the error. And you have the interval set to "16.6" milliseconds so it's spamming it fast and hard. And when I tested the code the "C stack overflow" didn't actually cause the lua to catch it either and it was that the whole script was stopped. But of course when you start talking stack overflow errors, I would expect odd behavior and for things to not always respond the same. Basically the call stack memory is being exceeded so the system kills whatever is causing it, thus the timer seems to stop. But the error message was never printed for me.

_________________
Back to top
View user's profile Send private message Visit poster's website
Estecka
How do I cheat?
Reputation: 0

Joined: 05 Mar 2022
Posts: 4
Location: France

PostPosted: Sun Mar 06, 2022 3:01 pm    Post subject: Reply with quote

The key difference between this and a regular C# program, is that any uncaught exception in a regular program would immediately kill the entire process, which is the best outcome we could hope for anyway. Here, this is not the case, the timer keeps running, doingspaghetti monsterknows what and spamming the error; ironically simply trying to replicate the usual behaviour of not having a try-catch block at the root of a program, requires here some kind of root try-catch.

Again, yes, proper error handling is preferable, but it only works after I've identified the errors that need to be handled. Until I know what kind of error I will need to handle or before I even realize there is an error I need to handle, this is the best I can get; and I can never be certain that all potential errors are being handled.

In any case, I've kept mulling it over, and here's a solution I came up with that should work with any error, catchable or not :
Code:

UncaughtError = false;

LuaLoop.onTimer = function()
   if (UncaughtError) then
      -- terminate timer
      return;
   end
   UncaughtError = true;
   --  script logic
   UncaughtError = false;
end

This does the error checking in the next iteration of the loop instead. A bit hacky, but it gets the work done.

Quote:
when I tested the code the "C stack overflow" didn't actually cause the lua to catch it

Odd, a "C stackoverflow" is definitely being caught by pcall on my side; at the very least I see it in the print I do right after pcall.
I'd send over the exact cheat table I using it in, but for some reason the size limit for uploading *.ct is only 8 Bytes...

_________________
Y s'taient cachés les steaks hachés.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4706

PostPosted: Sun Mar 06, 2022 3:11 pm    Post subject: Reply with quote

There are Lua errors and there are pascal exceptions. It seems like the Lua environment doesn't care about pascal exceptions.

I guess you could try to acquire a critical section at the start of the loop and release it at the end if there aren't any errors. If you can't acquire it at the start, then it clearly wasn't released, and you can stop the timer early there.
(this is more or less what you're doing with UncaughtError)

I don't know what you're doing, but if pcall really seems like the best solution, you're probably doing something wrong. In all my experience with using Lua in CE, you really don't need to be handling errors like this. The only circumstance I can think of is if you're writing a library that uses some user-provided code as a callback or something. Even then, in most cases, it's fine to not use pcall.

This sounds stupid but the best error handling strategy really is to not generate errors in the first place. e.g. if you're assigning some numeric value to MemoryRecord.Value, make sure the string is a number first.
Code:
local n = tonumber(newValue)
if n then
  memrec.Value = tostring(n)
end

When writing tables, stuff happens. CE might crash or lock up when you mess up. It doesn't matter how "safe" you try to make your code with pcall or other methods- it'll happen regardless. Enable auto-saving and you'll be fine.

Lua is a scripting language. If you want stronger guarantees like type safety and good error handling, use some other language.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Estecka
How do I cheat?
Reputation: 0

Joined: 05 Mar 2022
Posts: 4
Location: France

PostPosted: Sun Mar 06, 2022 3:53 pm    Post subject: Reply with quote

Quote:
The only circumstance I can think of is if you're writing a library that uses some user-provided code as a callback or something.

Well yes, this pretty much the mindset I'm going with here.
I'm not particularly concerned about CE crashing without saving, but I'll still try to ease out the burns where I know one tend to happen.

Quote:
If you want stronger guarantees like type safety and good error handling, use some other language.

What other languages are there one can use with CE in that way ?
I mostly went with Lua because it was the most readily available, and the most noticeably advertised within CE's menus and UI.

_________________
Y s'taient cachés les steaks hachés.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25807
Location: The netherlands

PostPosted: Sun Mar 06, 2022 3:56 pm    Post subject: Reply with quote

you can use a hybrid of lua and any other language.

e.g a plugin in c# and for gui access in CE use lua as a control interface

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites