Is it possible to throw a fake stack trace in dart?
For example, I have this code:
final FakeStartContext startContext = FakeStartContext(
runOverride: () async => throw Exception(fakeError),
);
It is overriding a function by throwing a fake exceptionMsg to it. Is there a way to throw a fake stack trace in addition to the fake error as well? Like something similar to this:
final FakeStartContext startContext = FakeStartContext(
runOverride: () async => throw Exception(fakeError, fakeStackTrace),
);
Such that it could be caught by catch(err, stacktrace)?
You can, because your code is asynchronous:
final FakeStartContext startContext = FakeStartContext(
runOverride: () async =>
await Future.error(Exception(fakeError), fakeStackTrace),
);
or just
final FakeStartContext startContext = FakeStartContext(
runOverride: () => Future.error(Exception(fakeError), fakeStackTrace),
);
It's not currently possible to do the same thing in a synchronous setting.
It doesn't help to to create a future containing your fake stack trace, because you can't wait for that future synchronously.
As mentioned, an Error.throwWithStackTrace(error, stack) function is scheduled to be added in Dart 2.16, which can synchronously throw an object and a stack trace of your choice.
Why use a fake stacktrace when you can easily get a real one?
For example:
thrower() {
ghi() => throw Exception('error');
def() => ghi();
abc() => def();
abc();
}
void main() {
try {
thrower();
} catch (e, st) {
print('Error $e, StackTrace: $st');
}
}
This will print something like this on Dart VM:
Error Exception: error, StackTrace: #0 thrower.ghi (file:///Users/renato/example.dart:2:12)
#1 thrower.def (file:///Users/renato/example.dart:3:15)
#2 thrower.abc (file:///Users/renato/example.dart:4:15)
#3 thrower (file:///Users/renato/example.dart:5:6)
#4 main (file:///Users/renato/example.dart:10:5)
#5 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:283:19)
#6 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
On dartpad.dev (JS) it prints this instead:
Error Exception: error, StackTrace: wrapException#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:363:17
throwExpression#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:377:15
call$0#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:3040:16
call$0#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:3046:23
call$0#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:3052:23
thrower#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:272:65
main#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:277:11
#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:3217:15
#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:3200:15
dartProgram#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:3211:5
#https://dartpad.dev/scripts/frame_dark.html line 19 > injectedScript:3219:3
replaceJavaScript#https://dartpad.dev/scripts/frame.js:19:19
messageHandler#https://dartpad.dev/scripts/frame.js:140:30
Related
I want to generate a random BigInt with dynamik length Bits. I am using the pointycastle package to get a SecureRandom BigInt.
import 'package:pointycastle/pointycastle.dart';
void main(List<String> arguments) {
print(gen(500));
}
BigInt gen(int Bits) {
var n = BigInt.from(1);
var ran = SecureRandom('Fortuna');
n = ran.nextBigInteger(Bits);
return n;
}
This line throws an exception:
n = ran.nextBigInteger(Bits);
StateError (Bad state: AES engine not initialised)
This is the complete error in the console:
Unhandled exception:
Bad state: AES engine not initialised
#0 AESFastEngine.processBlock
package:pointycastle/block/aes_fast.dart:109
#1 BlockCtrRandom.nextUint8
package:pointycastle/random/block_ctr_random.dart:55
#2 SecureRandomBase._randomBits
package:pointycastle/…/impl/secure_random_base.dart:55
#3 SecureRandomBase.nextBigInteger
package:pointycastle/…/impl/secure_random_base.dart:33
#4 AutoSeedBlockCtrRandom.nextBigInteger.<anonymous closure>
package:pointycastle/random/auto_seed_block_ctr_random.dart:69
#5 AutoSeedBlockCtrRandom._autoReseedIfNeededAfter
package:pointycastle/random/auto_seed_block_ctr_random.dart:81
#6 AutoSeedBlockCtrRandom.nextBigInteger
package:pointycastle/random/auto_seed_block_ctr_random.dart:68
#7 FortunaRandom.nextBigInteger
package:pointycastle/random/fortuna_random.dart:46
#8 gen
bin\encrypt.dart:10
#9 main
bin\encrypt.dart:4
#10 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:299:32)
#11 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
I can't seem to find a solution to this error message anywhere else. I hope u guys can help me. :D
It is not clear but if I look at the examples from the project it seems like you need to call the seed method. The following works for me:
import 'dart:math';
import 'dart:typed_data';
import 'package:pointycastle/pointycastle.dart';
void main(List<String> arguments) {
print(gen(500));
}
BigInt gen(int bits) {
final _sGen = Random.secure();
var n = BigInt.from(1);
var ran = SecureRandom('Fortuna');
ran.seed(KeyParameter(
Uint8List.fromList(List.generate(32, (_) => _sGen.nextInt(255)))));
n = ran.nextBigInteger(bits);
return n;
}
The example I was inspired by: https://github.com/PointyCastle/pointycastle/blob/master/tutorials/examples/import-demo/import-demo-1.dart
Welcome to Stackoverflow.
When using any part of Pointycastle you do need to instantiate the implementation objects.
In your code you are using
var ran = SecureRandom('Fortuna');
that uses the SecureRandom class.
Simply add
final rnd = new SecureRandom("AES/CTR/PRNG");
and kindly see the PointCastle SecureRandom example for further questions:
https://github.com/PointyCastle/pointycastle/blob/master/test/random/block_ctr_random_test.dart
I'm trying to caught an error from a completer.
Here, my method to decode a token
Future<Map> decode(String token) {
var completer = new Completer();
new Future(() {
List<String> parts = token.split(".");
Map result = {};
try {
result["header"] = JSON.decode(new String.fromCharCodes(crypto.CryptoUtils.base64StringToBytes(parts[0])));
result["payload"] = JSON.decode(new String.fromCharCodes(crypto.CryptoUtils.base64StringToBytes(parts[1])));
} catch(e) {
completer.completeError("Bad token");
return;
}
encode(result["payload"]).then((v_token) {
if (v_token == token) {
completer.complete(result);
} else {
completer.completeError("Bad signature");
}
});
});
return completer.future;
}
}
The call:
var test = new JsonWebToken("topsecret");
test.encode({"field": "ok"}).then((token) {
print(token);
test.decode("bad.jwt.here")
..then((n_tok) => print(n_tok))
..catchError((e) => print(e));
});
And this is the output
dart server.dart
eyJ0eXAiOiJKV1QiLCJhbGciOiJTSEEyNTYifQ==.eyJsdSI6Im9rIn0=.E3TjGiPGSJOIVZFFECJ0OSr0jAWojIfF7MqFNTbFPmI=
Bad token
Unhandled exception:
Uncaught Error: Bad token
#0 _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:820)
#1 _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#2 _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#3 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:126)
I don't understand why we tell me that my error is uncaught while it's printed...
I think you misused .. instead of . for chaining future. See https://www.dartlang.org/docs/tutorials/futures/#handling-errors
instead of
test.decode("bad.jwt.here")
..then((n_tok) => print(n_tok))
..catchError((e) => print(e));
can you try
test.decode("bad.jwt.here")
.then((n_tok) => print(n_tok))
.catchError((e) => print(e));
Have a look at this document about how Futures work - https://www.dartlang.org/articles/futures-and-error-handling/.
In particular there is an example which says:
myFunc()
.then((value) {
doSomethingWith(value);
...
throw("some arbitrary error");
})
.catchError(handleError);
If myFunc()’s Future completes with an error, then()’s Future
completes with that error. The error is also handled by catchError().
Regardless of whether the error originated within myFunc() or within
then(), catchError() successfully handles it.
That is consistent with what you're seeing.
I am getting this exception when I close the pool very soon after closing a query:
Uncaught Error: Bad state: Cannot write to socket, it is closed
Stack Trace:
#0 BufferedSocket.writeBufferPart (package:sqljocky/src/buffered_socket.dart:114:7)
#1 BufferedSocket.writeBuffer (package:sqljocky/src/buffered_socket.dart:108:27)
#2 _Connection._sendBufferPart (package:sqljocky/src/connection.dart:261:31)
#3 _Connection._sendBuffer (package:sqljocky/src/connection.dart:249:29)
#4 _Connection.processHandler (package:sqljocky/src/connection.dart:289:16)
#5 ConnectionPool._closeQuery.<anonymous closure> (package:sqljocky/src/connection_pool.dart:220:29)
#6 _rootRunUnary (dart:async/zone.dart:730)
#7 _RootZone.runUnary (dart:async/zone.dart:864)
#8 _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:488)
#9 _Future._propagateToListeners (dart:async/future_impl.dart:571)
#10 _Future._completeWithValue (dart:async/future_impl.dart:331)
#11 _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:393)
#12 _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:23)
#13 _asyncRunCallback (dart:async/schedule_microtask.dart:32)
#14 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:128)
Unhandled exception:
Bad state: Cannot write to socket, it is closed
#0 _rootHandleUncaughtError.<anonymous closure>.<anonymous closure> (dart:async/zone.dart:713)
#1 _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:23)
#2 _asyncRunCallback (dart:async/schedule_microtask.dart:32)
#3 _asyncRunCallback (dart:async/schedule_microtask.dart:36)
#4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:128)
the issue seems to be that the query close fires of a Future internally, so the close() function returns before the close is actually finished:
void _closeQuery(Query q, bool retain) {
_log.finest("Closing query: ${q.sql}");
for (var cnx in _pool) {
var preparedQuery = cnx.removePreparedQueryFromCache(q.sql);
if (preparedQuery != null) {
_waitUntilReady(cnx).then((_) {
_log.finest("Connection ready - closing query: ${q.sql}");
var handler = new _CloseStatementHandler(preparedQuery.statementHandlerId);
cnx.autoRelease = !retain;
cnx.processHandler(handler, noResponse: true);
});
}
}
}
The pool close happens immediately, it closes the socket right away. This means the query close (which is delayed till after the pool close due to the Future) fails, unable to send whatever information it needs to through the socket. I've opened a ticket to sqljocky at https://github.com/jamesots/sqljocky/issues/44 but I've received no replies, and I need a workaround if it's going to take a while to get a response.
This code has allowed me to replicate the issue 100% of the time:
Future _putMethod(RestRequest request) {
return new Future.sync(() {
mysql.ConnectionPool pool = getConnectionPool();
return pool.prepare("SELECT * FROM files").then((mysql.Query query) {
return query.execute().then((result) {
// Do something?
}).then((_) {
this._log.info("Closing");
query.close();
});
}).then((_) {
pool.close();
});
});
}
This is yet more a question than an answer but I can't put this code in a comment in a usable way.
You should ensure that you return the Future returned from every async invocation.
I don't know if the lines where I added the comment // added return are async invocations.
Can you please try and give feedback if this changes anything.
Future _putMethod(RestRequest request) {
return new Future.sync(() {
mysql.ConnectionPool pool = getConnectionPool();
return pool.prepare("SELECT * FROM files").then((mysql.Query query) {
return query.execute().then((result) {
// Do something? // also ensure that a Future of an async invocation is returned
}).then((_) {
this._log.info("Closing");
return query.close(); // added return
});
}).then((_) {
return pool.close(); // added return
});
});
}
I've modified little bit example from tutorial https://www.dartlang.org/docs/tutorials/streams/ by adding item after subscription:
import 'dart:async';
main() {
var data = new List<int>();
var stream = new Stream.fromIterable(data); // create the stream
// subscribe to the streams events
stream.listen((value) { //
print("Received: $value"); // onData handler
}); //
data.add(1);
}
And after running this program I've got:
Uncaught Error: Concurrent modification during iteration: _GrowableList len:1.
Stack Trace:
#0 ListIterator.moveNext (dart:_collection-dev/iterable.dart:315)
#1 _IterablePendingEvents.handleNext (dart:async/stream_impl.dart:532)
#2 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:661)
#3 _asyncRunCallback (dart:async/schedule_microtask.dart:18)
#4 _createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:11)
#5 _Timer._createTimerHandler._handleTimeout (timer_impl.dart:151)
#6 _Timer._createTimerHandler.<anonymous closure> (timer_impl.dart:166)
#7 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:93)
Putting data.add(1) before adding listener works as expected.
I've checked documentation about Stream and didn't found what I am doing wrong. I was expecting that listener will be fired in best case and just not fired in worst case, but not exception.
Is it expected behavior? If yes, please describe why.
The exception comes from you trying to modify the list while it is iterated over. This is unspecified behaviour in Dart (*), and the used implementation simply chose to throw an exception. While it is obfuscated by the asynchronous stuff happening in Stream.fromIterable, it basically is the same as if you tried to do this:
var data = [1,2,3];
for(var d in data) {
print(d);
data.add(d+10);
}
If you wrapped your data.add in another async call, for example with Timer.run(() => data.add(2)), it would "work". By that, I mean it wouldn't throw an exception.
Received: 2 still would not be printed. The stream will only send the elements that where already in the list at the time new Stream.fromIterable was called. After that, the stream is closed (onDone will be called), and modifications to the original list will not be sent to your listener.
(*) Source: iterator.dart in SDK 1.1.3 -- "If the object iterated over is changed during the iteration, the behavior is unspecified." Why the text on api.dartlang.org is different is beyond me.
EDIT
To answer the question in the comment: One way would be to use a StreamController.
// or new StreamController<int>.broadcast(), if you want to listen to the stream more than once
StreamController s = new StreamController<int>();
// produce periodic errors
new Timer.periodic(new Duration(seconds: 5), (Timer t) {
s.isClosed ? t.cancel() : s.addError("I AM ERROR");
});
// add some elements before subscribing
s.add(6);
s.add(9);
// this will close the stream eventually
new Timer(new Duration(seconds: 20), () => s.close());
// start listening to the stream
s.stream.listen((v) => print(v),
onError: (err) => print("An error occured: $err"),
onDone: () => print("The stream was closed"));
// add another element before the next event loop iteration
Timer.run(() => s.add(4711));
// periodically add an element
new Timer.periodic(new Duration(seconds: 3), (Timer t) {
s.isClosed ? t.cancel() : s.add(0);
});
// one more (will be sent before 4711)
s.add(4);
The List can't be modified while it is iterated over.
You need an iterable that doesn't have this limitation (e.g. custom implementation) for your example.
I made a simple web server but it crashes every time I am refreshing page many times in a short time. I just enter 127.0.0.1:8080 in my browser and then spam with F5. Here is the code to reproduce this issue:
void main()
{
HttpServer server = new HttpServer();
server.addRequestHandler((req) => true, handleGET);
server.listen('127.0.0.1', 8080);
}
void handleGET(HttpRequest req, HttpResponse res)
{
var requestedFile = ".${req.path}";
if(req.path == "/")
{
requestedFile = requestedFile.concat("index.html");
}
File file = new File(requestedFile);
file.exists().then((bool found) {
if(found)
{
file.openInputStream().pipe(res.outputStream);
}
else
{
res.statusCode = HttpStatus.NOT_FOUND;
res.outputStream.close();
}
});
}
The error I get is following:
Unhandled exception:
StreamException: Stream closed
#0 _SocketOutputStream._write (dart:io:6017:30)
#1 _HttpResponse._writeHeader (dart:io:5981:18)
#2 _HttpRequestResponseBase._ensureHeadersSent (dart:io:2696:19)
#3 _HttpResponse._streamClose (dart:io:2921:23)
#4 _HttpOutputStream.close (dart:io:3078:36)
#5 _pipe.<anonymous closure> (dart:io:6271:28)
#6 _BaseDataInputStream._checkScheduleCallbacks.issueCloseCallback (dart:io:6231:59)
#7 _Timer._createTimerHandler._handleTimeout (dart:io:6804:28)
#8 _Timer._createTimerHandler._handleTimeout (dart:io:6812:7)
#9 _Timer._createTimerHandler.<anonymous closure> (dart:io:6820:23)
#10 _ReceivePortImpl._handleMessage (dart:isolate-patch:37:92)
Often before this mayor exception I receive a bunch of warnings like WSASend failed: 10053 but those don't crash the server. I work on Windows if this problem is related to some specific implementation.
Because you are hitting reload very quickly, your code ends up trying to write to a socket that has already been closed. Hence, you should probably catch StreamException and just ignore it. It could be argued that the io library should help you out a bit more. I just filed this bug:
http://code.google.com/p/dart/issues/detail?id=7334&thanks=7334&ts=1355280746