Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

broken docs or feature on "Simple TCP Example" #26777

Closed
iwelch opened this issue Apr 10, 2018 · 9 comments
Closed

broken docs or feature on "Simple TCP Example" #26777

iwelch opened this issue Apr 10, 2018 · 9 comments
Labels
domain:docs This change adds or pertains to documentation domain:io Involving the I/O subsystem: libuv, read, write, etc.

Comments

@iwelch
Copy link

iwelch commented Apr 10, 2018

Just copied from the docs:

julia> @async begin
                 server = listen(2001)
                 while true
                     sock = accept(server)
                     @async while isopen(sock)
                         write(sock,readline(sock))
                     end
                 end
             end
Task (runnable) @0x000000010d1f3610

julia> clientside = connect(2001)
TCPSocket(RawFD(22) open, 0 bytes waiting)

julia> @async while true
                  write(STDOUT,readline(clientside))
              end
Task (runnable) @0x0000000126b90250

julia> println(clientside,"Hello World from the Echo Server")

julia> println(clientside,"Hello World from the Echo Server")

julia> println(clientside,"Hello World from the Echo Server")

julia> println(clientside,"Hello World from the Echo Server")

julia> close(clientside)
Hello World from the Echo ServerHello World from the Echo ServerHello World from the Echo ServerHello World from the Echo Server
julia> ERROR (unhandled task failure): ArgumentError: stream is closed or unusable
Stacktrace:
 [1] check_open(::TCPSocket) at ./stream.jl:251
 [2] uv_write(::TCPSocket, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:795
 [3] unsafe_write(::TCPSocket, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:832
 [4] write(::TCPSocket, ::String) at ./strings/string.jl:71
 [5] macro expansion at ./REPL[1]:6 [inlined]
 [6] (::##2#4)() at ./task.jl:335

oh, and the doc example would be better if the echo server would put something in front by itself, like "ECHO> ". /iaw

@vtjnash
Copy link
Sponsor Member

vtjnash commented Apr 11, 2018

There’s definely at least a missing let block there. Since it’s clearly trying to capture the value of sock, but is instead capturing the binding

@iwelch
Copy link
Author

iwelch commented Apr 11, 2018

to be clear---it is not that I miscoded by me. it is your example out of the docs on

https://docs.julialang.org/en/stable/manual/networking-and-streams/

regards,

/iaw

@JeffBezanson
Copy link
Sponsor Member

@vtjnash on master sock will get a new binding on each while loop iteration, so that part should be fine now. The problem is that readline was changed not to include the line break, so we need to update the docs to pass keep=true here.

The next issue is that readline returns "" on a closed stream; we might want to give an error instead.

Another possible issue is that write(sock, "") throws the stream is closed or unusable error even though there are zero bytes to write. We might want to allow "writing" zero bytes, but that's not so clear.

@JeffBezanson JeffBezanson added domain:docs This change adds or pertains to documentation domain:io Involving the I/O subsystem: libuv, read, write, etc. labels Apr 11, 2018
@JeffBezanson
Copy link
Sponsor Member

We could also change the while true in the second block to while isopen(clientside).

@iwelch
Copy link
Author

iwelch commented Apr 11, 2018

...and if you are fixing the whole example anyway, showing how you would recommend the outside can/shall close the server would be great, too.

/iaw

@jebej
Copy link
Contributor

jebej commented Apr 12, 2018

The problem is that readline was changed not to include the line break, so we need to update the docs to pass keep=true here.

That, or replace write by println.

@jebej
Copy link
Contributor

jebej commented Apr 12, 2018

Also, and I'm not sure if this is the right place to discuss this, but currently, closing the client and server "cleanly" would require a try block around the readline calls, and the accept call. Otherwise if either the server or client is closed during one of these calls an error would occur.

I assume that the most common case would be a client disconnecting during a server read. Is a try block an efficient way of dealing with such a situation?

@JeffBezanson
Copy link
Sponsor Member

Well, I'm very much not a fan of the unhandled task failure message (#12736). Without that, it would be clean by default. In the meantime, a try block is fine.

@jebej
Copy link
Contributor

jebej commented Apr 12, 2018

Without that, it would be clean by default.

What would happen if the client is closed during a client read operation, or during a server read operation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:docs This change adds or pertains to documentation domain:io Involving the I/O subsystem: libuv, read, write, etc.
Projects
None yet
Development

No branches or pull requests

4 participants