Bachmann1234 / java9_kernel

An ipython kernel for java 9
Apache License 2.0
72 stars 17 forks source link

broken kernel... pty issue? #24

Open hkarl opened 7 years ago

hkarl commented 7 years ago

Hi,

I've seen the message and experienced the problem: java_kernel does not work. However, not sure this is related to an update of ipython.

I tried the following setup on both a Linux debian (+/- uptodate) and an OsX 10.11.6

(jupyter) ~> pip freeze | grep jupyter
jupyter==1.0.0
jupyter-client==4.3.0
jupyter-console==4.1.1
jupyter-core==4.1.0
jupyterhub==0.6.1
(jupyter) ~> pip freeze | grep ipython
ipython==4.2.1
ipython-genutils==0.1.0

kulla, java-9 +/- up-to-date.

It works on OSX, but jshell does not start up. I dug down to the pexcept pseudo-terminal startup code. In bpyhton, this call blocks:

ptyprocess.PtyProcess.spawn(["/home/jupyterhub/java/jdk-9/bin/java", "-jar", "/home/jupyterhub/java/kulla/kulla.jar"])

and when looking at the user's processes, there is only a python3 child process, but no java process. Looks like the exec call in the PtyProcess does not take place?

Do you think that is the right direction to look for problems? (I understand you don't have time currently to do that yourself.)

Thanks a lot,

Holger

Bachmann1234 commented 7 years ago

That seems very likely. If you wanna take a stab at it I would appreciate it.

Bachmann1234 commented 7 years ago

And yeah. Life has gotten particularly busy recently and I have not had time for side projects. Good things mostly :-)

hkarl commented 7 years ago

ok - but not getting any progress. I asked here:

http://stackoverflow.com/questions/40937420/drive-java-kulla-from-pexpect-context-jupyter

Let's see... thanks!

nilsga commented 7 years ago

Is this still an issue? I'm running within the docker image, and it seems to work just fine?

dsblank commented 7 years ago

Appears to be an issue with later versions of jdk-9. Downgrading to jdk-9.ea+100 works for me.

hkarl commented 7 years ago

Yes, still an issue for me; with jdk build 9-ea+147

Good to know there is one version known to work ...

In case you are looking: this is available here http://download.java.net/java/jdk9/archive/100/binaries/jre-9-ea+100_linux-x64_bin.tar.gz

(Oracle makes you edit download links by hand to protect you against yourself ... 👎 )

nilsga commented 7 years ago

Yeah, build 132 works, but not 151.

Error:

Traceback (most recent call last):
  File "/opt/conda/lib/python3.5/site-packages/pexpect/spawnbase.py", line 150, in read_nonblocking
    s = os.read(self.child_fd, size)
OSError: [Errno 5] Input/output error

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/conda/lib/python3.5/site-packages/pexpect/expect.py", line 99, in expect_loop
    incoming = spawn.read_nonblocking(spawn.maxread, timeout)
  File "/opt/conda/lib/python3.5/site-packages/pexpect/pty_spawn.py", line 465, in read_nonblocking
    return super(spawn, self).read_nonblocking(size)
  File "/opt/conda/lib/python3.5/site-packages/pexpect/spawnbase.py", line 155, in read_nonblocking
    raise EOF('End Of File (EOF). Exception style platform.')
pexpect.exceptions.EOF: End Of File (EOF). Exception style platform.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/conda/lib/python3.5/runpy.py", line 184, in _run_module_as_main
    "__main__", mod_spec)
  File "/opt/conda/lib/python3.5/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/jovyan/javakernel/__main__.py", line 9, in <module>
    IPKernelApp.launch_instance(kernel_class=JavaKernel)
  File "/opt/conda/lib/python3.5/site-packages/traitlets/config/application.py", line 652, in launch_instance
    app.initialize(argv)
  File "<decorator-gen-120>", line 2, in initialize
  File "/opt/conda/lib/python3.5/site-packages/traitlets/config/application.py", line 87, in catch_config_error
    return method(app, *args, **kwargs)
  File "/opt/conda/lib/python3.5/site-packages/ipykernel/kernelapp.py", line 454, in initialize
    self.init_kernel()
  File "/opt/conda/lib/python3.5/site-packages/ipykernel/kernelapp.py", line 365, in init_kernel
    user_ns=self.user_ns,
  File "/opt/conda/lib/python3.5/site-packages/traitlets/config/configurable.py", line 412, in instance
    inst = cls(*args, **kwargs)
  File "/home/jovyan/javakernel/kernel.py", line 34, in __init__
    self._start_java_repl()
  File "/home/jovyan/javakernel/kernel.py", line 52, in _start_java_repl
    continuation_prompt=u'   ...> '
  File "/opt/conda/lib/python3.5/site-packages/pexpect/replwrap.py", line 55, in __init__
    self._expect_prompt()
  File "/opt/conda/lib/python3.5/site-packages/pexpect/replwrap.py", line 66, in _expect_prompt
    timeout=timeout)
  File "/opt/conda/lib/python3.5/site-packages/pexpect/spawnbase.py", line 390, in expect_exact
    return exp.expect_loop(timeout)
  File "/opt/conda/lib/python3.5/site-packages/pexpect/expect.py", line 105, in expect_loop
    return self.eof(e)
  File "/opt/conda/lib/python3.5/site-packages/pexpect/expect.py", line 50, in eof
    raise EOF(msg)
pexpect.exceptions.EOF: End Of File (EOF). Exception style platform.
<pexpect.pty_spawn.spawn object at 0x7f781850beb8>
command: /home/jovyan/jdk-9/bin/java
args: [b'/home/jovyan/jdk-9/bin/java', b'-jar', b'/home/jovyan/kulla.jar']
buffer (last 100 chars): ''
before (last 100 chars): 'void main(String[] args)\r\nor a JavaFX application class must extend javafx.application.Application\r\n'
after: <class 'pexpect.exceptions.EOF'>
match: None
match_index: None
exitstatus: None
flag_eof: True
pid: 21
child_fd: 34
closed: False
timeout: 30
delimiter: <class 'pexpect.exceptions.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
searcher: searcher_string:
    0: "jshell> "
    1: "   ...> "

This might have something to do with it: void main(String[] args) or a JavaFX application class must extend javafx.application.Application

nilsga commented 7 years ago

This might have something to do with it: http://hg.openjdk.java.net/jdk9/jdk9/langtools/rev/e5a42ddaf633

Seems like the main method in JShellTool is gone.

nilsga commented 7 years ago

If the launcher script changes java -jar kulla.jar to java -cp kulla.jar jdk.internal.jshell.tool.JShellToolProvider, it might work. Giving it a try.

nilsga commented 7 years ago

It gets rid of the kernel crash, but executing statements never terminates, so there's still something else that is wrong...

nilsga commented 7 years ago

I'm pretty sure this has something to do with ansi escape sequences to do. After digging deeper, it hangs when the jshell process outputs the sequence \x1b[6n

dsblank commented 7 years ago

@nilsga I agree, exactly. I also found this same issue when running jshell inside an Emacs shell.

But reverting back to an earlier jdk-9 avoids this problem.

nilsga commented 7 years ago

It would be very interesting to find out exact which version broke it, to pinpoint the exact change that caused it. For me, it works with build 132 but not 151. Have not tested any builds in between.

nilsga commented 7 years ago

Also, I don't think the kulla.jar is actually required anymore, since the downloadable JDK eap contains the jshell binary.

dsblank commented 7 years ago

@nilsga I believe that you are correct: using jdk-9ea+100/bin/jshell should work (although I did not try yet). I did try using pexpect with jdk-9ea+150/bin/jshelland that did NOT work because of the same control character issue described above.

Bachmann1234 commented 7 years ago

Im wondering if this is the kind of thing we could report to the openJDK team. Thoughts?

hkarl commented 7 years ago

That's very useful, thanks. But I am surprised you got ea+132 to work? It fails for me when trying multi-line commands (e.g., defining a class over multiple lines). ea-100 shows the same problem.

More precisely, it works for single-line commands.

It works for multi-line commands when running:

hkarl@gp1 ~/tmp % /home/jupyterhub/java/jdk-9/bin/java -jar $KULLA_HOME
|  Welcome to JShell -- Version 9-ea
|  Type /help for help

-> class A {
>> }
|  Added class A

but it fails with EOF when running under pexpect, just like in @nilsga comment above.

(Little program to test that without having to go through the jupyter context; example for ea-100 continuation prompts; same behavior with ea-132):

from pexpect import replwrap, EOF
jw = replwrap.REPLWrapper("/home/jupyterhub/java/jdk-9/bin/java -jar /home/jupyterhub/java/kulla/kulla.jar", "-> ", None, continuation_prompt=">> ")
print(jw)
commands = ("""class A {""", """}""")

for code in commands:
    print("-----")
    try:
        output = jw.run_command(code)
        print("output: ", output)
    except EOF:
        print("Ignoring EOF")
nilsga commented 7 years ago

I have only tested with the jupyter notebook, and it seems to work with ea-132. I did modify the kernel to run jshell directly though. Nevertheless, it might be that it is not possible to use the replwrapper with jshell anymore, and that one have to use a more "proper" ANSI terminal to capture output and send input.

dsblank commented 7 years ago

As @nilsga mentions, the notebook always sends complete cells, so this won't be a problem there. Likewise, if you always send complete code in the jupyter console, you won't see this problem.

BTW, if you use metakernel as the base, it will wait for a command completion in the console (for Java, it just waits for an empty line in input). But metakernel also has a wrapper around pexpect to try to fix some issues like this. I'm not sure if it will help in this situation though. Might be worth a try if you really want partial code in a cell. (metakernel also provides a common set of magics too, and shell, and parallel execution).

hkarl commented 7 years ago

@nilsga ah, ok, running jshell rather than kulla does the trick. Very nice! I am now using, in java_kernel:

            self.javawrapper = replwrap.REPLWrapper(
                "{}/bin/jshell".format(self.env['JAVA_9_HOME']),
                u'jshell> ',
                None,
                continuation_prompt=u'   ...> '

which seems to work (on ea-132).

(I want to use this for students, so actually need solutions that also work with imperfect input. This way, we are limited to jupyter notebook rather than console, but that's ok)

Thanks!

dsblank commented 7 years ago

@hkarl I am also using this with students... I have some customizations I'd be willing to share [1]. Last time I tried (Spring 2016) kulla.jar was pretty slow for even fairly small classes... how do you find it now?

[1] - https://athena.brynmawr.edu/jupyter/hub/dblank/public/CS206%20Data%20Structures/2016-Spring/Syllabus.ipynb

hkarl commented 7 years ago

@dsblank Interesting... we have so far done Python and will move into Java soon for the remaining of the term. Unfortunately, all my material is in German (don't ask ...). You could perhaps get some idea of our setup here: http://groups.uni-paderborn.de/fg-karl/lehre/ws1617/gp1/index.html

So no real experience on Kulla performance, but it looks like this just got dumped in favour of jshell, in any case. But that is also sure not to win any performance prices...

nilsga commented 7 years ago

jshell is Kulla (or rather, the other way around), btw. Kulla was just the "codename" before they merged it into the main JDK9 repository.

paoloantinori commented 7 years ago

@hkarl and @dsblank your setup sounds very interesting. do you guys have any repo out there that we can look at for a ready to go jupyter + java setup?

dsblank commented 7 years ago

I was hoping to have time to clean up the changes I have made, but alas not. But you are free to compare mine to this repo:

https://athena.brynmawr.edu/jupyter/hub/dblank/public/Experiments/Java9

I use metakernel (to get shell and other magics) and made some changes to the output. I think by default it echos everything, and I tried to remove that (doesn't work on lines longer than something like 70 chars). Echo is used to get the return values to show up in Jupyter return lines. And there are some times where getting the echo back displays useful information.

I'll be using this in class again in a few weeks, so I'll get back into it. Currently, I'm using the Calysto Processing kernel, which does compile Java (before converting to Javascript) and also has all of the cool Processing art/java simplifications:

https://github.com/Calysto/calysto_processing

If you are interested in that, I just made some local changes to it I'd be willing to share too (eg, println shows up in Jupyter's output area).

hkarl commented 7 years ago

I have a slightly different setup than Doug. I'm using it for a general-purpose programming class, so I want to stay fairly close to Java. Java9 actually is confusing those students already familiar with Java, but so be it.

In consequence, I ended up making relatively few changes:

--- a/javakernel/kernel.py
+++ b/javakernel/kernel.py
@@ -43,10 +43,7 @@ class JavaKernel(Kernel):
         sig = signal.signal(signal.SIGINT, signal.SIG_DFL)
         try:
             self.javawrapper = replwrap.REPLWrapper(
-                "{} -jar {}".format(
-                    self._JAVA_COMMAND,
-                    self._KULLA_LOCATION
-                ),
+                "{}/bin/jshell".format(self.env['JAVA_9_HOME']),
                 u'jshell> ',
                 None,
                 continuation_prompt=u'   ...> '

I observed issues similar to Doug; long lines cause problems; jshell parser does not treat things like

if (bla) {
   ...  }
else ... 

correctly; etc. So it is workable, but not perfect.

In total: YMMV!

dsblank commented 7 years ago

@hkarl We should try to put all of the good stuff here, when java9 is finally out.

I had updated java to ea132, and saw some weirdness this week. I think I'll retreat to ea100.

I also use nbgrader, but largely to disseminate/collect homework (everything is printed and manually graded). BUT, I think we can make the autograding work with some small changes. We made some enhancements in metakernel recently to make the Jupyter error handling API work properly, and I think we can do the same here. I'll try to look at that in a month, as it would be very useful.

hkarl commented 7 years ago

Sure... but I will not be able to do any work on this before our semester is over and the exams are done. Not before end of February...

On 19 Jan 2017, at 14:47, Doug Blank notifications@github.com wrote:

@hkarl We should try to put all of the good stuff here, when java9 is finally out.

I had updated java to ea132, and saw some weirdness this week. I think I'll retreat to ea100.

I also use nbgrader, but largely to disseminate/collect homework (everything is printed and manually graded). BUT, I think we can make the autograding work with some small changes. We made some enhancements in metakernel recently to make the Jupyter error handling API work properly, and I think we can do the same here. I'll try to look at that in a month, as it would be very useful.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.


Prof. Dr. Holger Karl Computer Networks group - http://wwwcs.upb.de/cs/cn/

Please send email, do not call me!

Need to talk to me? - http://tinyurl.com/k2qht4w


Q: Why is this email five sentences or less? A: http://five.sentenc.es

OAN: https://www.facebook.com/timothy.david.snyder/posts/1206636702716110

paoloantinori commented 7 years ago

Thank you guys for sharing your work. I'm currently having some issue with dependencies running on Fedora 25, so I'm trying to apply them to the Dockerbuild file and see if everything resolves find there.

thanks so far

paoloantinori commented 7 years ago

Thanks guys, it works. Unluckily trying with different newer versions fails and to output is returned.

dsblank commented 7 years ago

Some recent comments:

  1. I'm still using the older jar file due to the control codes in more modern jshells
  2. I've started a conversation at beakerx to discuss a jshell-based kernel (https://github.com/twosigma/beakerx/issues/5428)
  3. Even with the old kulla code, a recent change of use was quite nice: when you send code with newlines, there is about a 0.05 second delay per line. That adds up pretty quickly with 100-line code. The solution was to remove the newlines before sending to the jshell process. However, that created some complications when reporting errors. My recent version: https://github.com/dsblank/jupyter.brynmawr/blob/master/java9/kernel.py#L152-L188