Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Confused about remote_eval and string literals #29

Open
adigitoleo opened this issue Jan 6, 2022 · 7 comments
Open

Confused about remote_eval and string literals #29

adigitoleo opened this issue Jan 6, 2022 · 7 comments
Labels
bug Something isn't working

Comments

@adigitoleo
Copy link

adigitoleo commented Jan 6, 2022

It's really just a question, I'm not sure why this doesn't work. Today I was looking for a way to have a daemon running JuliaFormatter so I can occasionally quickly reformat messy files. I've got something that works when using DaemonMode.jl but not using this package.

Starting the server

DaemonMode.jl version:

jl --startup-file=no -e 'using JuliaFormatter,DaemonMode; serve()'

RemoteREPL.jl version:

jl --startup-file=no -e 'using JuliaFormatter,RemoteREPL; serve_repl()'

Client (code formatter script)

DaemonMode.jl version:

julia --startup-file=no -e "using DaemonMode; runexpr(\"\"\"format_file(\"$1\")\"\"\")"

RemoteREPL.jl version:

julia --startup-file=no -e "using RemoteREPL; RemoteREPL.remote_eval(\"\"\"format_file(\"$1\")\"\"\")"

Test file with bad formatting

begin
"""This is a badly formatted file"""
    a = 4
b = 2

c = (   "foo",
"bar")
end

The DaemonMode.jl version works as expected. The RemoteREPL.jl version connects to the server and then exits, but the code stays unformatted. From what I can see, DaemonMode just printlns the string to the socket, but here you have some more processing going on. I wonder if that is causing an issue with the triple-quoted strings or something?

@adigitoleo
Copy link
Author

The weird part is that I don't see any errors, so I'm not sure what's happening.

@c42f
Copy link
Collaborator

c42f commented Jan 7, 2022

I think your confusion here is due to the environment in which DaemonMode vs RemoteREPL evaluate their commands.

RemoteREPL is server-centred by default. This means that code

  • Executes in the Main module by default
  • Uses the current working directory of the server
  • Does not hijack the server's stdout and stderr

DaemonMode is client-centred by default. This means that code

  • Executes code in a temporary module
  • Runs code in the working directory of the client
  • Hijacks the server's stdout and stderr to send to the client

With this in mind, DaemonMode is more suited for your use case here. On the other hand, you could have debugged this issue interactively with RemoteREPL (it's a REPL, after all!). You might have seen something like the following:

chris@xyz:~/tmp$ pwd
/home/chris/tmp

chris@xyz:~/tmp$ julia -q
julia> using RemoteREPL

julia> connect_repl()
REPL mode remote_repl initialized. Press > to enter and backspace to exit.

julia@localhost> format_file("badfile1.jl")
ERROR: SystemError: opening file "badfile1.jl": No such file or directory
Stacktrace:
  [1] systemerror(p::String, errno::Int32; extrainfo::Nothing)
...

julia@localhost> pwd()
"/home/chris"

@c42f c42f added the bug Something isn't working label Jan 7, 2022
@c42f
Copy link
Collaborator

c42f commented Jan 7, 2022

For your use case, the following should work ok. The trick is to compute the abspath on the client side before sending to the server:

julia --startup-file=no -e 'using RemoteREPL; path=abspath(ARGS[1]); RemoteREPL.remote_eval("format_file(\"$path\")")' -- badfile.jl

The fact that remote_eval didn't show you an exception is a bug, I think.

I also opened #30 which would help with error reporting if JuliaFormatter writes to stdout.

@adigitoleo
Copy link
Author

Thanks for explaining, it makes sense. I'll stick to using DaemonMode for this for now, it also seems to be slightly faster (haven't benchmarked, just a hunch).

Thoughts on exporting remote_eval?

I was reading about sockets and streams the other day because it's all quite new to me, and it seems like it could be nice to have DaemonMode or this package falling back to unix sockets instead of TCP if both server and client are on the same (unix) host (better performance, possibly better secrity?). I wonder if you've tried using unix sockets before, or if you have some insights about that.

@c42f
Copy link
Collaborator

c42f commented Jan 7, 2022

it also seems to be slightly faster (haven't benchmarked, just a hunch)

Probably DaemonMode has lower startup time due to precompiling some things? Or perhaps because they don't need an ssh tunnel for transport over the open internet! Better startup time would be nice to have in RemoteREPL too, but it hasn't been a big priority yet as the use cases are different.

Thoughts on exporting remote_eval?

I think that would be fine, though I somehow feel it's not a great API :-)

falling back to unix sockets instead of TCP

Yes this definitely makes sense and I've been vaguely planning to do it at some point. Using unix domain sockets or windows named pipes would make sense on localhost and the Sockets stdlib even has a function to make it easy:

    listen(path::AbstractString) -> PipeServer

Create and listen on a named pipe / UNIX domain socket.

The main advantage is that it makes RemoteREPL secure to use on multi-user servers (at least on unix where you can use filesystem permissions to protect against other users on the system. I'm not sure about windows named pipes.). It should also help a bit with startup time.

@c42f
Copy link
Collaborator

c42f commented Jan 7, 2022

I opened an issue about this #31

@c42f
Copy link
Collaborator

c42f commented Mar 10, 2022

By the way, startup time for the client can be greatly reduced using the julia-r script here:

https://github.com/c42f/RemoteREPL.jl/blob/main/bin/julia-r

This sets some Julia options to make startup almost instant.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants