Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Two Types of Runtime Error?
Started by matt405 Mar 24 2017 02:11 PM

- - - - -
39 replies to this topic
[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

Just trying to understand a bit more about errors in Corona.

 

I seem to have two different types of runtime errors.

 

The first is one that creates an error and a dialogue box on the simulator or the device.  The other just generates a runtime error in the Build Panel, but does not crash the device.

 

Both say the words Error: Runtime error.

 

I would rather the behavior was consistent.

 

I am going to test if the unhandled error event captures this "under the hood" error...

 

Anyone else come across these differences?



[TOPIC: post.html]
#2

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

I can confirm that worryingly, these "other" Runtime errors do not get captured by 

 
local unhandledErrorListener = function( event )
    print( "We have a problem: " .. event.errorMessage )
end
 
Runtime:addEventListener( "unhandledError", unhandledErrorListener )
 
and do not crash the app.  Either on simulator or on the device.
 
An example of the error is: -
 
ERROR: Runtime error
\Development\Medication\3.x\creamInfoNew.lua:184: attempt to index field '?' (a nil value)
 
 
The error in question is that at line 184 the code is trying to reference a table array which is actually not there.  However, why is the runtime error not crashing the app??


[TOPIC: post.html]
#3

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

Found it - but I really need a solution.

 

This function, if called direct will generate a runtime error which present a dialogue box in the simulator and crashes the app: -

 

local test = {}
 
local test = function()
 
if tonumber(test[1].HasField) == 4 then
print("test1")
end
 
end
 
However, if this function is called as part of a Call Back Function following a network call (such as network.request) I only get the Runtime error in the output panel, but the app continues and does not crash...
 
I could really do with this behavior being consistent.  Any advice on how I can force the app to crash on a runtime error that may occur following a network call??


[TOPIC: post.html]
#4

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

I note that in the API documentation there is this line: -

 

"Network requests do not raise runtime errors in the event of failure so there is no need to wrap them in a Lua pcall() statement (errors are reported in the event sent to the network listener)."

 

However, the error is not being generated by the network request.  The error is being generated by a function that is called after the network request is called and the call back is called e.g.: -

 

 
local PostResponse2 = function(SaveRep)
 
if (SaveRep.isError) then
 -- OK - network called failed.... raise an error
else
     -- network call was OK - now do some more work
      test()
end
end
 
function scene:show(event)
 
http.MakeNetworkCall(PostResponse2,"GetCreamApplicationRecord",1)
 
end


[TOPIC: post.html]
#5

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

I have raised a Bug Report for this issue as I feel it is fundamental.  I don't think it should be allowed that you can have a situation where a thread of code could result in a un-trappable runtime error.  Any call after a succesful network.request can fail and the app will continue.  I have a work around which is to wrap any subsequent call with a timer.performWithDelay.  Not sure if any of the moderators have a view on this one...



[TOPIC: post.html]
#6

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,205 posts
  • Corona SDK

There are not two classes of errors... all errors will be trapped with Runtime:addEventListener( "unhandledError", unhandledErrorListener ) if the error is a true run time error.

 
Saying that all errors are not the same, some are trivial and handled within the run time, some are more important and need to be handled by the calling code.
 
Generally, it is up to the developer to handle errors in callback functions.  This is not a bug.  It is your responsibility to handle the post back and deal with it accordingly.  There is no way that a framework can possibly understand a callback of your network requests.  If your back-end service raises an error that will be included in the post back event.
 
The logic is that you will control the response to your network event and therefore you will also be responsible for your own error handling on your own response.  Makes perfect sense to me.


[TOPIC: post.html]
#7

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

Sorry, that is not correct.  If you read my post above, the response has not generated any error.   The runtime error is not being generated by the response.  The runtime error is being generated by a function called after a successful response.

 

In my code example above if I run the code without a network response the system generates a Run Time error.  The app crashes and the error is displayed on the page.  The Runtime:addEventListener( "unhandledError", unhandledErrorListener ) can catch the error.

 

If the same code is run, but with a network request as part of that call, same error is generated, the words Runtime Error is output to the build window, but the app does not crash, the app does not display any error and the Runtime:addEventListener will not catch it.

 

You may say that all network.requests have to be end points e.g. they take no further action.  However, practically this makes for a lot of unnecessary code, especially with a business app.

 

In my app before the scene loads I get some data from our cloud server.  I don't want the app to do anything else until the data has been retrieved, as dependent upon the data the screen may need to present data in a certain way.  The logical way of managing this is by having a function or set of functions called following a successful network request.  But, with this version of Corona, if any of those subsequent functions has some dodgy code or if the data is corrupted and causes a runtime error the app will not crash.  The app just carries on, potentially in a very unstable state.

 

I have a work around, but I have a load of revisions to make to implement it.

 

My work around is to wrap any subsequent calls after a successful response with a timer.performWithDelay().  Here is an example of how the above code now works with the new wrapper - runtime error is now generated as it should be: -

 

Please - can you run the below code and just see the treatment.  I would really appreciate it.

 

local test = {}


local test = function()




if tonumber(test[1].HasField) == 4 then
print("test1")
end


end



local function networkListener( event )


    if ( event.isError ) then
        print( "Network error: ", event.response )
    else
       -- toggle these two commands to see the different treatment of the error
       -- test()
        timer.performWithDelay(1, function() return test() end)
    end
end




  
-- Access Google 
network.request( "http://www.google.com", "GET", networkListener )

 

 





[TOPIC: post.html]
#8

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,205 posts
  • Corona SDK

Curious.... both raised an error (as expected) but there is a difference if it's raised inline or via a timer.  

 

There should be no difference between how the error is raised and a global catch all should fire but it doesn't.

 

This is the most simple use case where there is no "ERROR" printed

 

function unhandledErrorListener( event )
  print("ERROR")
end
Runtime:addEventListener("unhandledError", unhandledErrorListener)


local function networkListener( event )
  a = a + nil
end
network.request("http://www.google.com", "GET", networkListener)

All network requests need an end point handler - this is a requirement of the framework.  I just have empty function and point all callbacks to it if I need no post-processing on the network request.  Or you could just do this

network.request("http://www.google.com", "GET", function() end)

 

Anyway, I confirm your findings.



[TOPIC: post.html]
#9

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

Thank you for checking it out.  I have raised it as a bug through the bug reporting portal - however I am not sure if that is active.  Hopefully one of the main guys will see this thread and have a view...



[TOPIC: post.html]
#10

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,205 posts
  • Corona SDK

Last time I submitted a bug report the portal had a bug (oh the irony).  Send an email and include a main.lua that shows the problem - you can use my code as that is the most simple case.

 

Send to support@coronalabs.com



[TOPIC: post.html]
#11

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

Email sent.  Thanks a lot Adrian for your help.



[TOPIC: post.html]
#12

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,622 posts
  • Enterprise

The bug report didn't have an attached project, but I was able to take the provided code and create a project for engineering to look at.

 

Rob



[TOPIC: post.html]
#13

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

Thanks Rob. Not having raised an issue like this before, do you know if I will be told if the bug is fixed in a future build or should I just look out for it in the daily builds etc? Thanks again for passing it on. Keep up the good work - big fan of Corona!!

[TOPIC: post.html]
#14

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,622 posts
  • Enterprise

The task has this forum post link in it. Normally we announce it in the release notes for the daily builds. If the engineer can find the thread or if I can, we will try and update the thread as well. Ideally when the bug closes out, we will close out the support ticket which should trigger an email to you as well.

 

Rob



[TOPIC: post.html]
#15

Perry Clarke

[GLOBAL: userInfoPane.html]
Perry Clarke
  • Moderator

  • 850 posts
  • Corona Staff

Unfortunately, the documentation on the unhandledError listener is somewhat opaque and needs to be improved:
 

These events occur when an application experiences a runtime error. They are only dispatched to the global Runtime object.

 
The second sentence describes what you are seeing since callbacks and listeners are effectively in their own runtime (for an internal CoronaSDK definition of "runtime") but the consequences of that are not stated which are that errors in callbacks and listener code are not caught.
 
Having said that, it would be much better if the unhandledError listener worked more consistently and we will look into that.



[TOPIC: post.html]
#16

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,205 posts
  • Corona SDK

I've also found that recently errors in network.request() callbacks don't always log errors to the console either.

 

This is compounded if you then call another function from that callback as there is zero error handling available in any (nested) code called from the context of the callback.

 

I don't remember this behaviour always being this way.



[TOPIC: post.html]
#17

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

Thanks Perry for looking at this. I just want to underline the potential issue with the way the network.request currently works.  If your network.request call is to get some data you will inevitably want to do something with that data after it has returned.  The obvious thing to do is to put code in after the callback function has returned to process that data.  But, the way Corona currently works, ANY functions called after the callback has returned will not generate any error.  They will not crash the app.

 

If you imagine your network.request getting a lot of data.  If you have written lots of code to process that data on return - potentially configure screens based on that data - there is a lot of code that could go wrong, but the app will never fail and any error generated cannot be trapped.

 

I think this behavior is not ideal and could be very impactful for any apps which consume large amounts of data and dynamically configures screens based on that data returned...



[TOPIC: post.html]
#18

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,622 posts
  • Enterprise

When I tested the code that was posted in @adrianm's post above, I got a run time error in my call back. The problem is that the code that tries to handle the exception isn't handling the exception, correct?
 

Rob



[TOPIC: post.html]
#19

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,205 posts
  • Corona SDK

Exactly Rob...

 

Here is an example to support my previous comment.  "ERROR" is not printed and, more worryingly, no error reported to the console for the divide by 0 error (for me with 3049 anyway)

 

function unhandledErrorListener( event )
  print("ERROR")
end
Runtime:addEventListener("unhandledError", unhandledErrorListener)

local function divideByZero(a)
  return a / 0
end

local function networkListener( event )
  divideByZero(5)
end
network.request("http://www.google.com", "GET", networkListener)


[TOPIC: post.html]
#20

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

No, I think it is a lot worse that that Rob. From my perspective the impact could be pretty serious. Yes, I agree it says the words Runtime Error in the console window and the execution of any code on that thread has stopped, but the app does not crash. I tested it on an iPad. There is nothing when the app runs to inform you that the code has generated a runtime error. In fact the app continues to receive interaction from the end user. My definition of a runtime error is that the program that generates it stops working. In this case, a runtime error is generated, but the programme continues, potentially in a imbalanced state. And there is no way of informing the end user that something wrong has happened as we can't catch the error anyway. I would prefer it if the app crashed - in its current state, apps could be "crashing" all the time, but no one would ever know and functionality could be continuing, potentially with incomplete screens or with incomplete data. I'll be honest. The more I have think about it, the more worried I am.

[TOPIC: post.html]
#21

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,622 posts
  • Enterprise

So your problem is the opposite of @adrianm's. His situation does generate a run time error, it's just not captured. You're saying that they are not being generated at all, correct?

 

Rob



[TOPIC: post.html]
#22

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

No, sorry Rob, it is the same issue - I am just struggling to get everyone on the same page on this one (time zones etc). And Adrian has just not yet seen all of the aspects of it. I have spent a good week looking at this as the issue has potential to be massive for my apps. Adrian very kindly had a quick look in response to my forum post. If you have time run the use case that Adrian has created on an app. You will see that the app does not crash. Yes, the words runtime error are generated in a console window, but I would not call that in itself a runtime error. To be fair the simulator does not crash either, so that behaves the same. The problem Adrian is describing is one manifestation of the same problem. Please look into it in more detail if you can as I really believe this is a serious one...

[TOPIC: post.html]
#23

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,205 posts
  • Corona SDK

I agree... all runtime errors should abort program execution.  It is up to the developer to allow the runtime error to be suppressed only if they are sure it won't destabilise their program - by using a pcall() for example.

 

There are two issues here and neither are good.  

 

1. the runtime errors are not trapped by the unhandledError listener,

2. sometimes errors are not even raised on callback code (see my second use case above).

 

This is much more of an issue with heavily network-dependent apps.

 

In my game for example, players can visit other cities.  This obviously uses a network.request() and processes the response to display another city.  If some invalid data is returned I have no way or trapping the error and the thread simply aborts.  This can leave my game in an unstable state.  If I could trap the error I could roll back the game state and try again (or disable the action).



[TOPIC: post.html]
#24

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,205 posts
  • Corona SDK

Hi Corona, is there any update on this?

 

Non-trappable errors on callbacks are bad but callback code that just stops when the main thread continues is a nightmare.

 

Thanks



[TOPIC: post.html]
#25

matt405

[GLOBAL: userInfoPane.html]
matt405
  • Contributor

  • 173 posts
  • Corona SDK

Yes please - an update on this would be useful.  In one of my apps I have over 400 possible locations where we have network calls that could cause an issue.  Refactoring this code with my timer workaround is not ideal.  A solution from Corona would be great...  :)




[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]