attempt at better error recovery
- I often find that opening up driver.love and sending any message gets my app unwedged. Retrying should be easy. Just press a key. - There's really no reason for the app to become unresponsive while waiting for code changes. This approach tries to address both. Press any key to retry, or show the error right on the window while I whip out driver.love. You can also copy the message to the clipboard by hitting 'c'. Drawbacks of this approach: - nobody's going to read the message. I myself didn't notice the default support for copying the error message for _months_. - more complexity for anyone reading the code to parse. More stuff that can go wrong. Any errors within the handler will crash the app hard. (Though now there's less code in the handler, so maybe this is an improvement on that score.) The best plan is still to not rely on this too much. Don't ship bugs.
This commit is contained in:
parent
71c82e5c09
commit
a2451aa26e
31
live.lua
31
live.lua
|
@ -296,25 +296,18 @@ end
|
|||
|
||||
-- return nil to continue the event loop, non-nil to quit
|
||||
function live.handle_error(err)
|
||||
-- draw a pause indicator on screen
|
||||
love.graphics.setColor(1,0,0)
|
||||
love.graphics.rectangle('fill', 10,10, 3,10)
|
||||
love.graphics.rectangle('fill', 16,10, 3,10)
|
||||
love.graphics.present()
|
||||
-- print stack trace here just in case we ran the app through a terminal
|
||||
local stack_trace = debug.traceback('Error: '..tostring(err), --[[stack frame]]2):gsub('\n[^\n]+$', '')
|
||||
print(stack_trace)
|
||||
print('Look in the driver for options to investigate further.')
|
||||
print("(You probably can't close the app window at this point. If you don't have the driver set up, you might need to force-quit.)")
|
||||
-- send stack trace to driver and wait for a response
|
||||
Mode = 'error'
|
||||
local stack_trace = debug.traceback('Error: ' .. tostring(err), --[[stack frame]]2):gsub('\n[^\n]+$', '')
|
||||
live.send_run_time_error_to_driver(stack_trace)
|
||||
local buf
|
||||
repeat
|
||||
buf = live.receive_from_driver()
|
||||
love.timer.sleep(0.001)
|
||||
until buf
|
||||
if buf == 'QUIT' then
|
||||
return true
|
||||
Error_message = 'Something is wrong. Sorry!\n\n'..stack_trace..'\n\n'..
|
||||
"(Note: function names above don't include outer tables. So functions like on.draw might show up as just 'draw', etc.)\n\n"..
|
||||
'Options:\n'..
|
||||
'- press "ctrl+c" (without the quotes) to copy this message to your clipboard to send to me: ak@akkartik.com\n'..
|
||||
'- press any other key to retry, see if things start working again\n'..
|
||||
'- run driver.love to try to fix it yourself. As you do, feel free to ask me questions: ak@akkartik.com\n'
|
||||
Error_count = Error_count+1
|
||||
if Error_count > 1 then
|
||||
Error_message = Error_message..('\n\nThis is error #%d in this session; things will probably not improve in this session. Please copy the message and send it to me: ak@akkartik.com.'):format(Error_count)
|
||||
end
|
||||
live.run(buf)
|
||||
print(Error_message)
|
||||
end
|
||||
|
|
50
main.lua
50
main.lua
|
@ -13,13 +13,19 @@ require 'edit'
|
|||
Editor_state = {}
|
||||
|
||||
function App.version_check()
|
||||
-- available modes: run, version_check
|
||||
Mode = 'version_check'
|
||||
-- available modes: run, error
|
||||
Mode = 'run'
|
||||
Error_message = nil
|
||||
Error_count = 0
|
||||
-- we'll reuse error mode on load for an initial version check
|
||||
Supported_versions = {'11.4', '11.3', '11.2', '11.1', '11.0'} -- keep these sorted in descending order
|
||||
local major, minor = love.getVersion()
|
||||
Version = major..'.'..minor
|
||||
if array.find(Supported_versions, Version) then
|
||||
Mode = 'run'
|
||||
if array.find(Supported_versions, Version) == nil then
|
||||
Mode = 'error'
|
||||
Error_message = ("This app doesn't support version %s; please use version %s. Press any key to try it with this version anyway."):format(Version, Supported_versions[1])
|
||||
print(Error_message)
|
||||
-- continue initializing everything; hopefully we won't have errors during initialization
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -139,48 +145,51 @@ function App.filedropped(file)
|
|||
end
|
||||
|
||||
function App.draw()
|
||||
if Mode == 'version_check' then
|
||||
love.graphics.setColor(1,1,0)
|
||||
love.graphics.rectangle('fill', 30,30, 400,400)
|
||||
love.graphics.setColor(0,0,0)
|
||||
love.graphics.printf(("This app doesn't support version %s; please use version %s. Press any key to try it with this version anyway."):format(Version, Supported_versions[1]), 40,40, 400)
|
||||
if Mode == 'error' then
|
||||
love.graphics.setColor(0,0,1)
|
||||
love.graphics.rectangle('fill', 0,0, App.screen.width, App.screen.height)
|
||||
love.graphics.setColor(1,1,1)
|
||||
love.graphics.printf(Error_message, 40,40, 600)
|
||||
return
|
||||
end
|
||||
if on.draw then on.draw() end
|
||||
end
|
||||
|
||||
function App.update(dt)
|
||||
if Mode == 'version_check' then return end
|
||||
if Mode == 'error' then return end
|
||||
Current_time = Current_time + dt
|
||||
-- some hysteresis while resizing
|
||||
if Current_time < Last_resize_time + 0.1 then
|
||||
return
|
||||
end
|
||||
Cursor_time = Cursor_time + dt
|
||||
-- listen for commands in both 'error' and 'run' modes
|
||||
live.update(dt)
|
||||
if on.update then on.update(dt) end
|
||||
if Mode == 'run' then
|
||||
if on.update then on.update(dt) end
|
||||
end
|
||||
end
|
||||
|
||||
function App.mousepressed(x,y, mouse_button)
|
||||
if Mode == 'version_check' then return end
|
||||
if Mode == 'error' then return end
|
||||
Cursor_time = 0 -- ensure cursor is visible immediately after it moves
|
||||
if on.mouse_press then on.mouse_press(x,y, mouse_button) end
|
||||
end
|
||||
|
||||
function App.mousereleased(x,y, mouse_button)
|
||||
if Mode == 'version_check' then return end
|
||||
if Mode == 'error' then return end
|
||||
Cursor_time = 0 -- ensure cursor is visible immediately after it moves
|
||||
if on.mouse_release then on.mouse_release(x,y, mouse_button) end
|
||||
end
|
||||
|
||||
function App.wheelmoved(dx,dy)
|
||||
if Mode == 'version_check' then return end
|
||||
if Mode == 'error' then return end
|
||||
Cursor_time = 0 -- ensure cursor is visible immediately after it moves
|
||||
if on.mouse_wheel_move then on.mouse_wheel_move(dx,dy) end
|
||||
end
|
||||
|
||||
function App.focus(in_focus)
|
||||
if Mode == 'version_check' then return end
|
||||
if Mode == 'error' then return end
|
||||
if in_focus then
|
||||
Last_focus_time = Current_time
|
||||
end
|
||||
|
@ -195,7 +204,12 @@ end
|
|||
-- App.keypressed is defined in keychord.lua
|
||||
|
||||
function App.keychord_press(chord, key)
|
||||
if Mode == 'version_check' then return end
|
||||
if Mode == 'error' then
|
||||
if chord == 'C-c' then
|
||||
love.system.setClipboardText(Error_message)
|
||||
end
|
||||
return
|
||||
end
|
||||
-- ignore events for some time after window in focus (mostly alt-tab)
|
||||
if Current_time < Last_focus_time + 0.01 then
|
||||
return
|
||||
|
@ -205,7 +219,7 @@ function App.keychord_press(chord, key)
|
|||
end
|
||||
|
||||
function App.textinput(t)
|
||||
if Mode == 'version_check' then return end
|
||||
if Mode == 'error' then return end
|
||||
-- ignore events for some time after window in focus (mostly alt-tab)
|
||||
if Current_time < Last_focus_time + 0.01 then
|
||||
return
|
||||
|
@ -215,7 +229,7 @@ function App.textinput(t)
|
|||
end
|
||||
|
||||
function App.keyreleased(key, scancode)
|
||||
if Mode == 'version_check' then
|
||||
if Mode == 'error' then
|
||||
Mode = 'run'
|
||||
return
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue