Use love error handler back to back

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Syrius_Märx
Prole
Posts: 3
Joined: Sun Mar 27, 2022 6:10 pm

Use love error handler back to back

Post by Syrius_Märx »

Hello everyone !
I have question about error handling.

With the function love.errorhandler(msg) we can do stuff and go back to the game if an unexpected error occurs. It’s really nice.
BUT, it works once. The second time an error occurs, love.errorhandler(msg) seems to be void and the game just end.
Here is a very simplified version of my code :

Code: Select all

BOOT = 0

function love.errorhandler(msg)
  CRASH = true
  love.window.setMode(640,360)
  while CRASH do
    love.event.pump()
    for e, a, b, c in love.event.poll() do
      if e == "keypressed" and a == "escape" then
        CRASH = false
        return love.run() -- restart mainloop beginning with love.load
      end
    end
    love.graphics.printf("Game crashed "..tostring(BOOT).." time(s)\n\n\nPress ESC to restart", 0, 160, 640, 'center')
    love.graphics.present()
    love.timer.sleep(0.1)
  end
end

function love.load()
  BOOT = BOOT + 1
  CLOCK = 0
  love.window.setMode(640,360)
  love.graphics.printf("Game is loading\n#"..tostring(BOOT), 0, 160, 640, 'center')
  love.graphics.present()
  love.timer.sleep(2)
end

function love.update(dt)
  CLOCK = CLOCK + dt
  if love.keyboard.isDown('space') then fakefunction() end 
end

function love.draw()
  love.graphics.printf("Game is running for:\n"..tostring(math.floor(CLOCK)).." sec\n\nPress SPACE to crash", 0, 160, 640,'center')
end

function love.quit()
  love.graphics.printf("THE END !", 0, 160, 640, 'center')
  love.timer.sleep(2)
end
  • Boot #1 is launch
  • Boot #2 is reboot after crash
  • Boot #3 never exists
How to go to boot #3 and further ?

I think I misanderstood something about the way it should work and I would appreciate some help.
It may be around the return love.run() but without this line, game stops at the end of love.errorhandler . . .
I already develop the parts about save log, restart a match, live hot fix with console but i'm stuck with the possibility to use error handlder back to back.

Hope I'm clear enough and you could help me !

Syrius
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: Use love error handler back to back

Post by ReFreezed »

love.errorhandler is just supposed to be used for error reporting right before the game quits - not to restore or restart the state of the game. If you return a function (which the `return love.run()` line does) that function is supposed to just display the error. LÖVE doesn't expect the game to continue at that point.

If you have a function call somewhere that you want to catch errors from you should wrap the call with pcall or xpcall and handle the error manually (instead of letting LÖVE know about the error and do things you don't want). If you want to restart the whole game after an error you can call love.event.quit("restart"). (Note that it doesn't work if we've reached the point when LÖVE calls love.errorhandler.)
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
Syrius_Märx
Prole
Posts: 3
Joined: Sun Mar 27, 2022 6:10 pm

Re: Use love error handler back to back

Post by Syrius_Märx »

Even if it's not supposed to be used like that, the fact is : it works fine . . . at least once.
It could be a powerfull tool for smoothly passing over critical errors (or for debugging).
What I understand is that return love.run() is not a root reboot, but a reboot whithin love.errorhandler which is not recursive itself. So the end of program happens.

I know pcall. I already use it, especially for system input/ouput. I also add conditionnals to secure against void variables.
But it never will catch all errors. That's the core of the problem, an 'unexpected error'.

Anyway thanks for the anwser, it was clear !

If anyone find a workaround in future, i'm still open to hear it.
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: Use love error handler back to back

Post by ReFreezed »

Syrius_Märx wrote: Mon Mar 28, 2022 8:33 pm it works fine . . . at least once.
(...)
What I understand is that return love.run() is not a root reboot, but a reboot whithin love.errorhandler which is not recursive itself. So the end of program happens.
The call to love.run() does not restart anything as far as LÖVE is concerned, and is not important. It's that LÖVE expects love.errorhandler to return a function that handles one frame during the time the error should be reported, before LÖVE quits. That's all. love.run() just happens to return such a function.

It's important to know why something works. You can continue doing things with graphics, sound, controller input etc. in the error handler because the program hasn't started shutting itself off yet when it's called. LÖVE could have simply printed out the error message to the console and shut down immediately when an uncaught error happened, but that's not very good user experience. Showing that an error happened graphically is less confusing than suddenly getting kicked out to the desktop, so LÖVE delays shutting things down until the user knows an error happened and is ready to close the window. Still, LÖVE's error handling only happens as a last line of defense against "getting kicked out to the desktop with no information" - if you want to handle an error yourself (in a non-hacky way) you have to catch it before LÖVE catches it.

Anyway, here's a way to catch errors and even using LÖVE's error handler to report the error, but without letting LÖVE itself catch and know about the error.

Code: Select all

local function reportErrorAndRestart(err)
	local errHandler  = love.errorhandler or love.errhand
	local errMainLoop = errHandler(err)

	repeat until errMainLoop() -- Repeat until the callback returns an exit code.

	-- We can restart the game now.
	love.load() -- Or call love.event.quit("restart").
end

local function onKeypressed(key)
	if key == "space" then  doesNotExist()  end -- Triggers an error.
end
local function onUpdate(dt)
	-- ...
end
local function onDraw()
	love.graphics.print("Running game!", 10, 10)
end

-- Wrap all your code in protected calls.
function love.keypressed(...)  xpcall(onKeypressed, reportErrorAndRestart, ...)  end
function love.update    (...)  xpcall(onUpdate    , reportErrorAndRestart, ...)  end
function love.draw      (...)  xpcall(onDraw      , reportErrorAndRestart, ...)  end
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
Syrius_Märx
Prole
Posts: 3
Joined: Sun Mar 27, 2022 6:10 pm

Re: Use love error handler back to back

Post by Syrius_Märx »

Ok, thanks for precisions.

I know the way i used it was a bit tricky
In a second hand, I was wondering about protect main functions. And you confirm it could be a solution.

I dont have time to test tonight but i'll post feedback in next days.
User avatar
pgimeno
Party member
Posts: 3713
Joined: Sun Oct 18, 2015 2:58 pm

Re: Use love error handler back to back

Post by pgimeno »

Syrius_Märx wrote: Mon Mar 28, 2022 8:33 pm I know pcall. I already use it, especially for system input/ouput. I also add conditionnals to secure against void variables.
But it never will catch all errors. That's the core of the problem, an 'unexpected error'.
Can you name an example of an error that pcall won't catch but love.errorhandler will?
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 8 guests