#351 Bug: Str is null

cgrinds Thu 28 Aug 2008

I'm confused. Why does this program:

class NullString {
  static Void main() {
    NullString().go
  }
  Void go() {
    a := Foo().start
    b := Foo().start
    c := Foo().start
    a.join
    b.join
    c.join
  }
}

const class Foo : Thread {
  new make() : super.make(){}
  override Obj run(){
    locals.set("value", 0)
    return this
  }
}

result in:

sys::NullErr: key is null
        at fan.sys.NullErr.<init>(NullErr.java:45)
        at fan.sys.NullErr.make(NullErr.java:31)
        at fan.sys.NullErr.make(NullErr.java:28)
        at fan.sys.NullErr.make(NullErr.java:21)
        at fan.sys.Map.set(Map.java:114)
        at fan.NullString_0.Foo.run(/C:/stuff/fan/NullString.fan:21)
        at fan.sys.Thread$Val.run(Thread.java:453)

The fcode looks fine:

--concurrency_examples::Foo : sys::Thread--
    [SourceFile] size=16
       NullString.fan
    [LineNumber] size=2
       15

  make () -> sys::Void [ctor public]
    [Code]
      0: LoadVar             0
      3: CallCtor            sys::Thread.make() -> sys::Void
      6: ReturnVoid
    [LineNumber] size=2
       16

  run () -> sys::Obj [override public virtual]
    [Code]
      0: CallStatic          sys::Thread.locals() -> [sys::Str:sys::Obj]
      3: LoadStr             value
      6: LoadInt             0
      9: CallVirtual         sys::Map.set(sys::Obj, sys::Obj) -> sys::Map
     12: Pop
     13: LoadVar             0
     16: ReturnObj
    [LineNumber] size=2
       17

brian Thu 28 Aug 2008

Chris - you're the man when it comes to finding bugs.

That bug is actually a race condition in the Java class loading where we emit from fcode to bytecode. I've fixed for the next build.

I don't have a unified diff handy, but if you want to fix yourself it is in jfan/fan/sys/FanClassLoader.java, add this to line 127:

e.printStackTrace();
}
}

// ensure pod is emitted with our constant pool before
// loading any classes inside of it (if this was the
// actual class to load, then we are done)
pod.emit();
if (typeName.equals("$Pod")) return pod.emit();

// if the type name ends with $ then this is a mixin body
// class being used before we have loaded the mixin interface,
// so load them both, then we should it registered by name;

cgrinds Thu 28 Aug 2008

Thanks Brian, that fixes the bug for me.

Login or Signup to reply.