Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unhandled Exception in Dart

Tags:

dart

I've written a webserver in Dart and have a question regarding exceptions. In my HttpServer requesthandler I've added a try-catch block around the entire method:

try{
 ...
} catch(e) {
 ...
}

So I expected that this would prevent any client request from crashing the webserver. The problem is that it can crash when certain exceptions are thrown from within this block (heavily nested in other modules, but still initiated from this block). The following is an example of such a exception:

Unhandled exception:
FutureUnhandledException: exception while executing Future
  Illegal argument(s)
original stack trace:
  #0      _StringBase._createFromCodePoints (dart:core-patch:1403:3)
  #1      _StringBase.createFromCharCodes (dart:core-patch:1400:33)
  #2      String.String.fromCharCodes (dart:core-patch:1788:43)
  #3      _StringDecoderBase.decoded (dart:io:6485:12)
  #4      _File.readAsString.<anonymous closure> (dart:io:1307:29)
  #5      _FutureImpl.transform.<anonymous closure> (bootstrap:881:37)

 #0      _FutureImpl._complete (bootstrap:844:11)
 #1      _FutureImpl._complete (bootstrap:848:5)
 #2      _FutureImpl._setException (bootstrap:873:14)
 #3      _CompleterImpl.completeException (bootstrap:948:30)
 #4      _FutureImpl.transform.<anonymous closure> (bootstrap:884:36)
 #5      _FutureImpl._complete (bootstrap:840:19)
 #6      _FutureImpl._complete (bootstrap:848:5)
 #7      _FutureImpl._setValue (bootstrap:862:14)
 #8      _CompleterImpl.complete (bootstrap:945:26)
 #9      _File.readAsBytes.<anonymous closure> (dart:io:1281:25)
 #10     _BaseDataInputStream._checkScheduleCallbacks.issueCloseCallback (dart:io:6345:59)
 #11     _Timer._createTimerHandler._handleTimeout (dart:io:6918:28)
 #12     _Timer._createTimerHandler._handleTimeout (dart:io:6926:7)
 #13     _Timer._createTimerHandler.<anonymous closure> (dart:io:6934:23)
 #14     _ReceivePortImpl._handleMessage (dart:isolate-patch:37:92)

Why doesn't this get catched in the try-catch block? It is thrown in code that is called from within it (even though it isn't shown in the stacktrace).

I expect that I've missed something about how exceptions work in Dart, so I hope you can enlighten me :)

like image 663
palantus Avatar asked Dec 11 '12 18:12

palantus


People also ask

How do you handle the unhandled exception in darts?

In order to catch all the exceptions in a block of code you wrap the code in try block and use multiple on-catch instructions to handle some specific exceptions, then use catch to handle all other unexpected exceptions, and finally use finally to run the code that should be invoked after the code in try block and in ...

What is an unhandled exception?

An unhandled exception is an error in a computer program or application when the code has no appropriate handling exceptions. Learn about the definition and examples of unhandled exceptions, and explore programming and exception handlers. Updated: 01/04/2022.

What is exception in Dart?

Dart Exceptions are the run-time error. It is raised when the program gets execution. The program doesn't report the error at compile time when the program runs internally and if Dart compiler found something not appropriate. Then, it reports run-time error and the execution of program is terminated abnormally.


2 Answers

With Future, you have to use the catchError method to deal with exceptions.

like image 182
Alexandre Ardhuin Avatar answered Sep 24 '22 20:09

Alexandre Ardhuin


Once you realize what is going on, understanding the issue is pretty simple.

The problem is: the semantics of traditional control flow constructs (if, while, try/catch/finally, return) is purely synchronous. They expect that the program flows just like its source code flows. Take a look at this:

1      try {
2        while (...) {
3          if (...) {
4            doSomething();
5            doSomethingElse();
6          }
7        }
8      } catch (e) {
9        print('oh no, something wrong happen! error: $e');
10     } finally {
11       print('done!');
12     }

This program works as a sequence. The line 1 is executed before line 2 which is executed before line 3 etc. Line 5 is executed immediatelly after line 4. Line 11 is executed after line 7, and if an exception happens, line 11 is also executed after line 9. That's what synchronous means.

However, synchronous programs are no longer good enough. Event handling is naturally asynchronous, and you will find events everywhere -- from user interfaces to highly scalable network servers. So if you write

1      try {
2        var text = 'this will be replaced by the content of the file';
3        new File('...').readAsText().then((result) {
4          text = result;
5          doSomethingThatMightCauseAnException(text);
6          print('read file, got $text');
7        });
8        print('invoked file read');
9        return text;
10     } catch (e) {
11       print('error: $e');
12     }

you have to understand that you are invoking an asynchronous operation (the readAsText method). In this program, line 2 executes after line 1 and line 3 goes after line 2, but line 4 doesn't execute after line 3. The file reading is invoked asynchronously (think "in the background") and the program continues. So in this situation, after line 3, you will get directly to line 8. And so the return statement on line 9 (which follows line 8) always returns the 'this will be replaced by the content of the file' text.

Then, the program goes on and on, until it is done (it exits the main function). But it doesn't stop, because there is some code running "in the background" and there is a handler registered for it (you registered the handler by calling the then method). Once the system finishes reading the file, it will call the handler (the anonymous function you passed to the then method). Only when there is no handler for some asynchronous invocation registered, the program can stop.

And now, you probably understand that the exception handler on line 10 can only catch an error that happens on line 3 (error opening the file). But if an exception happens on line 5, it can't be caught on line 10, because that catch handler is long gone.

The rest is just a matter of using the API properly. If you work with callbacks, you have to pass an success handler and an error handler, if you work with Futures, you have to call the then method with a success handler and the handleException method with an error handler.

like image 36
Ladicek Avatar answered Sep 26 '22 20:09

Ladicek