#2474 NullErr in fansh

elyashiv Thu 24 Sep 2015

When I quite fansh I usually just press Ctr-D. When I do this, I get a NullErr.

I guess this is a error, though it doesn't bother me too much, but it is an error, and probably not so complicated to fix.

I'm running on linux mint, using bash and Jline.

elyashiv Fri 25 Sep 2015

That's just getting weird...

I stopped being lazy, and figured out this bug will be easy to fix by my self. I cloned the source code, and added the following to the fansh/fan/Shell.fan file:

diff -r fd89993adbdd src/fansh/fan/Shell.fan
--- a/src/fansh/fan/Shell.fan	Wed Sep 23 17:17:28 2015 -0400
+++ b/src/fansh/fan/Shell.fan	Fri Sep 25 16:47:03 2015 +0300
@@ -31,6 +31,9 @@
       // input next line
       line := Env.cur.prompt("fansh> ")

+      Env.echo(line)
+      Env.echo(line.chars)
+
       // skip empty lines
       line = line.trim
       if (line.size == 0) continue

I compiled, and run the shell -

$ ./build.fan 
compile [fansh]
  Compile [fansh]
    FindSourceFiles [2 files]
    WritePod [lib/fan/fansh.pod]
BUILD SUCCESS [426ms]!
$ fansh
Fantom Shell v1.0.67 ('?' for help)
fansh> s := "abc"
s := "abc"
[115, 32, 58, 61, 32, 34, 97, 98, 99, 34]
abc
fansh> 

[,]
fansh> null
sys::NullErr: java.lang.NullPointerException
  fan.sys.FanStr.chars (FanStr.java:322)
  fansh::Shell.run (Shell.fan:35)
  fansh::Main.main (Shell.fan:224)
  java.lang.reflect.Method.invoke (Method.java:483)
  fan.sys.Method.invoke (Method.java:559)
  fan.sys.Method$MethodFunc.callList (Method.java:198)
  fan.sys.Method.callList (Method.java:138)
  fanx.tools.Fan.callMain (Fan.java:173)
  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)

First input is to check that I'm running the right version of the shell, and that the code I added works.

Second input is just pressing Enter. Works.

Third input is pressing Ctr-D. As you can see, I get a null, which raises a NullErr when trying to call a function.

Seems like the solution is simple - add a null check. Did it:

--- a/src/fansh/fan/Shell.fan	Wed Sep 23 17:17:28 2015 -0400
+++ b/src/fansh/fan/Shell.fan	Fri Sep 25 16:53:50 2015 +0300
@@ -31,6 +31,9 @@
       // input next line
       line := Env.cur.prompt("fansh> ")

+      if (line == null)
+        quit
+
       // skip empty lines
       line = line.trim
       if (line.size == 0) continue

Building results this -

Shell.fan(34,11): Comparison of non-nullable type 'sys::Str' to null

Well, how comes a non-nullable type is null?

SlimerDude Fri 25 Sep 2015

Hi elyashiv, thanks for looking into that!

Fantom Strs are backed by Java strings, and what you're seeing is a mis-match between the actual Java implementation and what the API has defined.

So Env.prompt() returns a non-nullable Str, the implementation of which can be found in BootEnv. This delegates to Java's System.console().readLine() which says:

A string containing the line read from the console, not including any line-termination characters, or null if an end of stream has been reached.

The sending Ctrl+D or EOF would probably result in null being passed back instead of an empty string.

To fix the error you're seeing, null could be handed in BootEnv but it'd probably be better / easier to change the prompt() signature to return a nullable Str? and have consumers of the method (like Shell.fan) deal with it.

elyashiv Sat 26 Sep 2015

Just found that InStream.readLine also returns a Str?, and Env.prompt shouldn't really be different.

elyashiv Sun 27 Sep 2015

Here is a patch:

diff -r a1c9989c98db src/fansh/fan/Shell.fan
--- a/src/fansh/fan/Shell.fan	Fri Sep 25 17:30:13 2015 -0400
+++ b/src/fansh/fan/Shell.fan	Sun Sep 27 14:59:02 2015 +0300
@@ -30,6 +30,12 @@
     {
       // input next line
       line := Env.cur.prompt("fansh> ")
+      
+      if (line == null)
+      {
+        quit
+        continue
+      }
 
       // skip empty lines
       line = line.trim
  
diff -r a1c9989c98db src/sys/fan/Env.fan
--- a/src/sys/fan/Env.fan	Fri Sep 25 17:30:13 2015 -0400
+++ b/src/sys/fan/Env.fan	Sun Sep 27 14:59:02 2015 +0300
@@ -158,7 +158,7 @@
   ** See [Setup]`docTools::Setup#jline` for JLine integration.
   ** Default implementation delegates to `parent`.
   **
-  virtual Str prompt(Str msg := "")
+  virtual Str? prompt(Str msg := "")
 
   **
   ** Prompt the user to enter a password from standard input with echo

It passed the test written already.

brian Mon 28 Sep 2015

I pushed a fix

Login or Signup to reply.