Errors thrown out of actors are not printed until a "get". We have talked about this before but a solution to this will save time when debugging such code. maybe a flag on startup? Here's a simplified version
using concurrent
class ActorTest{
Void main(){
Actor(ActorPool()){
throw Err()
}.send(null)
Actor.sleep(5sec)
}
}
brianSat 30 Jun 2012
A flag on startup for debug might be useful, but I don't think it would work in practice. In a real system, you might have 100s of exceptions getting thrown often as just normal flow of behavior. In most cases they are getting caught by client and handled. If you logged everyone one of those even with a flag I think it would be too noisy. The trick would be to figure out a way to log only those messages that don't get accessed by a Future.
SlimerDudeSat 30 Jun 2012
Okay, an admission of guilt - all my Actors extend the following:
const class AfActor : Actor {
private const static Log log := Log.get("AfActor")
new make(ActorPool pool, Str stashName) : super(pool) { }
Obj? get(|Obj?->Obj?| f) {
return send(f).get
}
override Obj? receive(Obj? msg) {
func := (msg as |Obj?->Obj?|)
try {
return func.call(this)
} catch (Err e) {
// if the func has a return type, then an the Err is rethrown on assignment
// else we log the Err so the Thread doesn't fail silently
if (func.returns == Void#)
log.err("AfActor receive()", e)
throw e
}
}
}
so I can send / run / return code within the global thread space. But note my receive function logs errors if the calling function doesn't have a return value.
Steve.
AkcelistoSun 1 Jul 2012
No. I writed not about err stack is printed only if get is called.
Look at my example code. I call get and stack is printed. But stack is reduced.
Akcelisto Fri 29 Jun 2012
Why actors do not print stack trace? This lead to redundant code.
const class MyActor : Actor{ new make():super(ActorPool()){ } override Obj? receive(Obj? msg){ try{ //... }catch(Err e){ e.trace throw e } } }Akcelisto Fri 29 Jun 2012
Oops. Stack is printed. But there is case when not printed:
class TraceTest{ Void main(){ try{ Json.json }catch(Err e){ echo("proper stack") e.trace } try{ a := MyActor() a.send(0).get }catch(Err e){ echo("reduced stack") e.trace } } } class Json{ static Str json(){ d := Int:Int[:] d[0] = 0 return JsonOutStream.writeJsonToStr(d) } } const class MyActor : Actor{ static const ActorGames cur := ActorGames() new make():super(ActorPool()){ } override Obj? receive(Obj? msg){ if(msg==0){ return Json.json() } return null } } proper stack sys::CastErr: java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String fan.sys.Map.each (Map.java:347) util::JsonOutStream.writeJsonMap (JsonOutStream.fan:86) util::JsonOutStream.writeJson (JsonOutStream.fan:50) util::JsonOutStream.writeJsonToStr (JsonOutStream.fan:24) igruktorServer::JsonQ.json (TraceTest.fan:30) igruktorServer::TraceTest.main (TraceTest.fan:7) java.lang.reflect.Method.invoke (Unknown) fan.sys.Method.invoke (Method.java:559) fan.sys.Method$MethodFunc.callOn (Method.java:230) fan.sys.Method.callOn (Method.java:139) fanx.tools.Fan.callMain (Fan.java:175) fanx.tools.Fan.executeType (Fan.java:140) fanx.tools.Fan.execute (Fan.java:41) fanx.tools.Fan.run (Fan.java:298) fanx.tools.Fan.main (Fan.java:336) reduced stack sys::CastErr: java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String concurrent::Future.get (Future.java:100) concurrent::Future.get (Future.java:57) igruktorServer::TraceTest.main (TraceTest.fan:14) java.lang.reflect.Method.invoke (Unknown) fan.sys.Method.invoke (Method.java:559) fan.sys.Method$MethodFunc.callOn (Method.java:230) fan.sys.Method.callOn (Method.java:139) fanx.tools.Fan.callMain (Fan.java:175) fanx.tools.Fan.executeType (Fan.java:140) fanx.tools.Fan.execute (Fan.java:41) fanx.tools.Fan.run (Fan.java:298) fanx.tools.Fan.main (Fan.java:336) sys::CastErr: java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String concurrent::Actor._dispatch (Actor.java:236) concurrent::Actor._work (Actor.java:199) concurrent::ThreadPool$Worker.run (ThreadPool.java:255)kaushik Sat 30 Jun 2012
Errors thrown out of actors are not printed until a "get". We have talked about this before but a solution to this will save time when debugging such code. maybe a flag on startup? Here's a simplified version
using concurrent class ActorTest{ Void main(){ Actor(ActorPool()){ throw Err() }.send(null) Actor.sleep(5sec) } }brian Sat 30 Jun 2012
A flag on startup for debug might be useful, but I don't think it would work in practice. In a real system, you might have 100s of exceptions getting thrown often as just normal flow of behavior. In most cases they are getting caught by client and handled. If you logged everyone one of those even with a flag I think it would be too noisy. The trick would be to figure out a way to log only those messages that don't get accessed by a Future.
SlimerDude Sat 30 Jun 2012
Okay, an admission of guilt - all my Actors extend the following:
const class AfActor : Actor { private const static Log log := Log.get("AfActor") new make(ActorPool pool, Str stashName) : super(pool) { } Obj? get(|Obj?->Obj?| f) { return send(f).get } override Obj? receive(Obj? msg) { func := (msg as |Obj?->Obj?|) try { return func.call(this) } catch (Err e) { // if the func has a return type, then an the Err is rethrown on assignment // else we log the Err so the Thread doesn't fail silently if (func.returns == Void#) log.err("AfActor receive()", e) throw e } } }meaning my Actors look like:
const class Pulsar : AfActor { Void stop() { send |->| { ...stuff... } } }so I can send / run / return code within the global thread space. But note my
receivefunction logs errors if the calling function doesn't have a return value.Steve.
Akcelisto Sun 1 Jul 2012
No. I writed not about err stack is printed only if
getis called.Look at my example code. I call
getand stack is printed. But stack is reduced.This depend on which type exception is throwed.