JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.47k stars 5.46k forks source link

ERROR: write: i/o error (EIO) with the new WSL #24310

Closed kavir1698 closed 5 years ago

kavir1698 commented 6 years ago

Since updating my Windows to the Fall creators update, I get the following error in REPL (using Windows Subsystem for Linux), when printing special objects to the screen.

Julia Version 0.6.0 (2017-06-19 13:05 UTC)

Example 1: DataFrames

julia> using DataFrames

julia> df = DataFrame(A = 1:4, B = ["M", "F", "F", "M"]);   # this works find

julia> df = DataFrame(A = 1:4, B = ["M", "F", "F", "M"])
4×2 DataFrames.DataFrame
│ Row │ A │ B   │
Error showing value of type DataFrames.DataFrame:
ERROR: write: i/o error (EIO)
Stacktrace:
 [1] try_yieldto(::Base.##296#297{Task}, ::Task) at ./event.jl:189
 [2] wait() at ./event.jl:234
 [3] uv_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:811
 [4] unsafe_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:832
 [5] unsafe_write(::Base.TTY, ::Base.RefValue{UInt8}, ::Int64) at ./io.jl:293
 [6] write(::Base.TTY, ::UInt8) at ./stream.jl:873
 [7] write(::IOContext{Base.Terminals.TTYTerminal}, ::Char) at ./io.jl:337
 [8] showrows(::IOContext{Base.Terminals.TTYTerminal}, ::DataFrames.DataFrame, ::UnitRange{Int64}, ::UnitRange{Int64
}, ::Array{Int64,1}, ::Bool, ::Symbol, ::Bool) at /home/alirv/.julia/v0.6/DataFrames/src/abstractdataframe/show.jl:3
66
 [9] show(::IOContext{Base.Terminals.TTYTerminal}, ::DataFrames.DataFrame, ::Bool, ::Symbol, ::Bool) at /home/alirv/
.julia/v0.6/DataFrames/src/abstractdataframe/show.jl:459
 [10] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::MIME{Symbol("text/plain")}, ::DataFrames.DataFrame)
 at ./REPL.jl:122
 [11] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::DataFrames.DataFrame) at ./REPL.jl:125
 [12] display(::DataFrames.DataFrame) at ./multimedia.jl:194
 [13] eval(::Module, ::Any) at ./boot.jl:235
 [14] print_response(::Base.Terminals.TTYTerminal, ::Any, ::Void, ::Bool, ::Bool, ::Void) at ./REPL.jl:144
 [15] print_response(::Base.REPL.LineEditREPL, ::Any, ::Void, ::Bool, ::Bool) at ./REPL.jl:129
 [16] (::Base.REPL.#do_respond#16{Bool,Base.REPL.##26#36{Base.REPL.LineEditREPL,Base.REPL.REPLHistoryProvider},Base.
REPL.LineEditREPL,Base.LineEdit.Prompt})(::Base.LineEdit.MIState, ::Base.AbstractIOBuffer{Array{UInt8,1}}, ::Bool) a
t ./REPL.jl:646

Example 2: printing documentation of some functions

help?> triu
search: triu triu! istriu Distributed UpperTriangular LowerTriangular tril trim tril! trim! trimvar trigamma

  triu(M)

  Upper triangle of a matrix.

     Example
    ≡≡≡≡≡≡≡≡≡

julia> a = ones(4,4)
  4Error showing value of type Base.Markdown.MD:
ERROR: write: i/o error (EIO)
Stacktrace:
 [1] try_yieldto(::Base.##296#297{Task}, ::Task) at ./event.jl:189
 [2] wait() at ./event.jl:234
 [3] uv_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:811
 [4] unsafe_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:832
 [5] unsafe_write(::Base.TTY, ::Base.RefValue{UInt8}, ::Int64) at ./io.jl:293
 [6] write(::Base.TTY, ::UInt8) at ./stream.jl:873
 [7] write(::Base.Terminals.TTYTerminal, ::Char) at ./io.jl:334
 [8] write(::Base.Terminals.TTYTerminal, ::SubString{String}) at ./strings/io.jl:123
 [9] print(::Base.Terminals.TTYTerminal, ::SubString{String}) at ./strings/io.jl:122
 [10] print(::Base.Terminals.TTYTerminal, ::SubString{String}, ::Char, ::Vararg{Char,N} where N) at ./strings/io.jl:
40
 [11] (::Base.Markdown.##172#173{Base.Markdown.Code})(::Base.Terminals.TTYTerminal) at ./markdown/render/terminal/re
nder.jl:89
 [12] with_output_format(::Function, ::Array{Symbol,1}, ::Base.Terminals.TTYTerminal) at ./markdown/render/terminal/
formatting.jl:25
 [13] term(::Base.Terminals.TTYTerminal, ::Base.Markdown.Code, ::Int64) at ./markdown/render/terminal/render.jl:86
 [14] term(::Base.Terminals.TTYTerminal, ::Array{Any,1}, ::Int64) at ./markdown/render/terminal/render.jl:14
 [15] term(::Base.Terminals.TTYTerminal, ::Base.Markdown.MD, ::Int64) at ./markdown/render/terminal/render.jl:17
 [16] term(::Base.Terminals.TTYTerminal, ::Array{Any,1}, ::Int64) at ./markdown/render/terminal/render.jl:11
 [17] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::Base.Markdown.MD) at ./markdown/render/terminal/ren
der.jl:148
 [18] display(::Base.Markdown.MD) at ./multimedia.jl:194
 [19] eval(::Module, ::Any) at ./boot.jl:235
 [20] print_response(::Base.Terminals.TTYTerminal, ::Any, ::Void, ::Bool, ::Bool, ::Void) at ./REPL.jl:144
 [21] print_response(::Base.REPL.LineEditREPL, ::Any, ::Void, ::Bool, ::Bool) at ./REPL.jl:129
 [22] (::Base.REPL.#do_respond#16{Bool,Base.Docs.#helpmode,Base.REPL.LineEditREPL,Base.LineEdit.Prompt})(::Base.Line
Edit.MIState, ::Base.AbstractIOBuffer{Array{UInt8,1}}, ::Bool) at ./REPL.jl:646
czlee commented 6 years ago

I think it might falter every time it hits any non-ASCII character, and I think this might be closer to the underlying cause. When printing documentation, if it crashes, it prints up until the first non-ASCII character and then fails to print the non-ASCII charater. For example, in the above example printing the documentation for triu, it gets up to the 4×4, then fails on the ×. Similar results happen for inv, div, and others with any non-ASCII character, though strangely works fine.

The same error (for the first seven items on the stack trace) occurs if you just try to print a string with a non-ASCII character in it. Interestingly, it only happens if it tries to show the string—if you just print the string with print(), there's no problem.

julia> print("The next character is ×")
The next character is ×
julia> "The next character is ×"
"The next character is Error showing value of type String:
ERROR: write: i/o error (EIO)
Stacktrace:
 [1] try_yieldto(::Base.##296#297{Task}, ::Task) at ./event.jl:189
 [2] wait() at ./event.jl:234
 [3] uv_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:811
 [4] unsafe_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:832
 [5] unsafe_write(::Base.TTY, ::Base.RefValue{UInt8}, ::Int64) at ./io.jl:293
 [6] write(::Base.TTY, ::UInt8) at ./stream.jl:873
 [7] write(::IOContext{Base.Terminals.TTYTerminal}, ::Char) at ./io.jl:334
 [8] print at ./char.jl:45 [inlined]
 [9] escape_string(::IOContext{Base.Terminals.TTYTerminal}, ::String, ::String) at ./strings/io.jl:236
 [10] print_quoted at ./strings/io.jl:253 [inlined]
 [11] show at ./strings/io.jl:124 [inlined]
 [12] show(::IOContext{Base.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::String) at ./replutil.jl:147
 [13] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::MIME{Symbol("text/plain")}, ::String) at ./REPL.jl:122
 [14] display(::Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, ::String) at ./REPL.jl:125
 [15] display(::String) at ./multimedia.jl:218
 [16] eval(::Module, ::Any) at ./boot.jl:235
 [17] print_response(::Base.Terminals.TTYTerminal, ::Any, ::Void, ::Bool, ::Bool, ::Void) at ./REPL.jl:144
 [18] print_response(::Base.REPL.LineEditREPL, ::Any, ::Void, ::Bool, ::Bool) at ./REPL.jl:129
 [19] (::Base.REPL.#do_respond#16{Bool,Base.REPL.##26#36{Base.REPL.LineEditREPL,Base.REPL.REPLHistoryProvider},Base.REPL.LineEditREPL,Base.LineEdit.Prompt})(::Base.LineEdit.MIState, ::Base.AbstractIOBuffer{Array{UInt8,1}}, ::Bool) at ./REPL.jl:646

This doesn't actually get at the underlying problem, but hopefully it's a step closer if anyone else looks at this 🙂

Edit: Actually, on second inspection I realized this doesn't really add very much that we didn't already know. But here's an upvote for the issue, anyway.

This is on Julia version 0.6.2, on Ubuntu on Windows 10 version 1709.

vtjnash commented 6 years ago

It’s informative to see, but since this isn’t a bug with Julia, you should post the same comments on the WSL issue tracker. They’ve been pretty responsive in the past

czlee commented 6 years ago

Sure, will do. In order to try and provide something useful to the WSL developers, I kept digging. Since I found a workaround, I thought I may as well post it here.

Here's a workaround:

import Base.write

function write(s::IO, ch::Char)
    c = reinterpret(UInt32, ch)
    if c < 0x80
        return write(s, c%UInt8)
    elseif c < 0x800
        return write(s, [
          (( c >> 6         ) | 0xC0) % UInt8,
          (( c        & 0x3F) | 0x80) % UInt8,
        ])
    elseif c < 0x10000
        return write(s, [
          (( c >> 12        ) | 0xE0) % UInt8,
          (((c >> 6)  & 0x3F) | 0x80) % UInt8,
          (( c        & 0x3F) | 0x80) % UInt8,
        ])
    elseif c < 0x110000
        return write(s, [
          (( c >> 18        ) | 0xF0) % UInt8,
          (((c >> 12) & 0x3F) | 0x80) % UInt8,
          (((c >> 6)  & 0x3F) | 0x80) % UInt8,
          (( c        & 0x3F) | 0x80) % UInt8,
        ])
    else
        return write(s, '\ufffd')
    end
end

That redefines write in base/io.jl:329-348, to do the same thing but by calling write(::IO, ::Array{UInt8}) rather than write(::IO, ::UInt8).

Why this works I don't fully understand. It seems like it works fine when is passed an array of chars, but not when it's passed any single char outside the ASCII range. Maybe the OS expects the entire Unicode character in one go or something (whereas Linux will happily keep the leading byte around in its buffer?). Then when escape_string() (base/strings/io.jl:232-247) passes characters to write() one by one, it hits a problem with the function above; print(), in contrast, just passes the byte array to the OS.

Anyway, I'll report this to the WSL folks some time soon.

grandtiger commented 6 years ago

I am using Julia 0.7.0 from WSL (Ubuntu 18.04) with ODBC Driver 17 for SQL Server installed.

I got the same ERROR: IOError: write: i/o error (EIO). Meanwhile, pyodbc works perfectly in Python using the same ODBC driver.

julia> version = ODBC.query(dsn, "SELECT @@Version")
1×1 DataFrame. Omitted printing of 1 columns
│ Row │ Error showing value of type DataFrame:
ERROR: IOError: write: i/o error (EIO)
Stacktrace:
 [1] try_yieldto(::typeof(Base.ensure_rescheduled), ::Base.RefValue{Task}) at ./event.jl:196
 [2] wait() at ./event.jl:255
 [3] uv_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:786
 [4] unsafe_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:834
 [5] unsafe_write at ./io.jl:512 [inlined]
 [6] unsafe_write(::Base.TTY, ::Base.RefValue{UInt8}, ::Int64) at ./io.jl:510
 [7] write at ./io.jl:513 [inlined]
 [8] write(::Base.TTY, ::UInt8) at ./stream.jl:876
 [9] write(::REPL.Terminals.TTYTerminal, ::UInt8) at ./io.jl:224 (repeats 2 times)
 [10] write at ./io.jl:571 [inlined]
 [11] showrows(::IOContext{REPL.Terminals.TTYTerminal}, ::DataFrame, ::UnitRange{Int64}, ::UnitRange{Int64}, ::Array{Int64,1}, ::Bool, ::Bool, ::Symbol, ::Bool) at /home/george/.julia/packages/DataFrames/utxEh/src/abstractdataframe/show.jl:374
 [12] show(::IOContext{REPL.Terminals.TTYTerminal}, ::DataFrame, ::Bool, ::Symbol, ::Bool) at /home/george/.julia/packages/DataFrames/utxEh/src/abstractdataframe/show.jl:461
 [13] show at /home/george/.julia/packages/DataFrames/utxEh/src/abstractdataframe/show.jl:447 [inlined]
 [14] show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::DataFrame) at ./sysimg.jl:195
 [15] display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl:131
 [16] display(::REPL.REPLDisplay, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl:135
 [17] display(::DataFrame) at ./multimedia.jl:287
 [18] #invokelatest#1 at ./essentials.jl:691 [inlined]
 [19] invokelatest at ./essentials.jl:690 [inlined]
 [20] print_response(::IO, ::Any, ::Any, ::Bool, ::Bool, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl:154
 [21] print_response(::REPL.AbstractREPL, ::Any, ::Any, ::Bool, ::Bool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl:139
 [22] (::getfield(REPL, Symbol("#do_respond#40")){Bool,getfield(REPL, Symbol("##50#59")){REPL.LineEditREPL,REPL.REPLHistoryProvider},REPL.LineEditREPL,REPL.LineEdit.Prompt})(::Any, ::Any, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl:708
 [23] #invokelatest#1 at ./essentials.jl:691 [inlined]
 [24] invokelatest at ./essentials.jl:690 [inlined]
 [25] run_interface(::REPL.Terminals.TextTerminal, ::REPL.LineEdit.ModalInterface, ::REPL.LineEdit.MIState) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v0.7/REPL/src/LineEdit.jl:2261
 [26] run_frontend(::REPL.LineEditREPL, ::REPL.REPLBackendRef) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl:1029
 [27] run_repl(::REPL.AbstractREPL, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v0.7/REPL/src/REPL.jl:191
 [28] (::getfield(Base, Symbol("##831#833")){Bool,Bool,Bool,Bool})(::Module) at ./logging.jl:311
 [29] #invokelatest#1 at ./essentials.jl:691 [inlined]
 [30] invokelatest at ./essentials.jl:690 [inlined]
 [31] macro expansion at ./logging.jl:308 [inlined]
 [32] run_main_repl(::Bool, ::Bool, ::Bool, ::Bool, ::Bool) at ./client.jl:340
 [33] exec_options(::Base.JLOptions) at ./client.jl:252
 [34] _start() at ./client.jl:432
musm commented 6 years ago

I cannot reproduce on WSL and julia 1.0 on Windows 10 build 17758.1

czlee commented 6 years ago

With Julia 1.0 and Windows 10 version 1803 (build 17134.285), it's doing better for me than it was on Julia 0.6:

help?> mapslices
search: mapslices

  mapslices(f, A; dims)

  Transform the given dimensions of array A using function f. f is called on each slice of A of the form
  A[...,:,...,:,...]. dims is an integer vector specifying where the colons go in this expression. The results are
  concatenated along the remaining dimensions. For example, if dims is [1,2] and A is 4-dimensional, f is called on
  A[:,:,i,j] for all i and j.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> a = reshape(Vector(1:16),(2,2,2,2))
  2×2×2×2 Array{Int64,4}:
  [:, :, 1, 1] =
   1  3
   2  4

[[... rest of documentation ... yay!]]

but it still seems to run into the same thing sometimes:

julia> "The next character is ×"
"The next character is Error showing value of type String:
ERROR: IOError: write: i/o error (EIO)
Stacktrace:
 [1] try_yieldto(::typeof(Base.ensure_rescheduled), ::Base.RefValue{Task}) at ./event.jl:196
 [2] wait() at ./event.jl:255
 [3] uv_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:786
 [4] unsafe_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:834
 [5] unsafe_write at ./io.jl:509 [inlined]
 [6] unsafe_write(::Base.TTY, ::Base.RefValue{UInt8}, ::Int64) at ./io.jl:507
 [7] write at ./io.jl:510 [inlined]
 [8] write(::Base.TTY, ::UInt8) at ./stream.jl:876
 [9] write(::REPL.Terminals.TTYTerminal, ::UInt8) at ./io.jl:224 (repeats 2 times)

[[... rest of stacktrace ...]]

and even with other characters in documentation:

help?> sqrt
search: sqrt isqrt

[[... documentation for sqrt(x) ... ]]

  sqrt(A::AbstractMatrix)

  If A has no negative real eigenvalues, compute the principal matrix square root of A, that is the unique matrix X
  with eigenvalues having positive real part such that X^2 = A. Otherwise, a nonprincipal square root is returned.

  If A is symmetric or Hermitian, its eigendecomposition (eigen) is used to compute the square root. Otherwise, the
  square root is determined by means of the Björck-Hammarling method [^BH83], which computes the complex Schur form
  (schur) and then the complex square root of the triangular factor.

  │ [^BH83]
  Error showing value of type Markdown.MD:
ERROR: IOError: write: i/o error (EIO)
Stacktrace:
 [1] try_yieldto(::typeof(Base.ensure_rescheduled), ::Base.RefValue{Task}) at ./event.jl:196
 [2] wait() at ./event.jl:255
 [3] uv_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:786
 [4] unsafe_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:834
 [5] unsafe_write at ./io.jl:509 [inlined]

[[... rest of stacktrace ...]]

I believe the character that it would be printing next here is Å: https://github.com/JuliaLang/julia/blob/v1.0.0/stdlib/LinearAlgebra/src/dense.jl#L660

I'm not in the Windows Insider Program, so don't have 17758, let me know if you think this is important.

(I never did end up reporting this to WSL, I was trying to collect more information at a lower level using a short C program and it ended up in my too-hard basket. Sorry.)

Also, the workaround I posted above no longer works in Julia 0.7 or Julia 1.0. I assume changes in io.jl made it no longer sensible. That's not a problem, just mentioning here for the benefit of anyone else who stumbles upon this page looking for a workaround.

musm commented 6 years ago

@czlee I can't seem to trigger this bug with any of the stated examples in this issue.

This is likely an WSL bug that was fixed. The new windows update (which I think will be released very soon) will fix this issue.

czlee commented 6 years ago

Cool, that's useful, thanks, I'll check and report after the next Windows GA release.

OkonSamuel commented 5 years ago

The bug is still there. I get the I/o error when trying to display a dataframe using Julia in WSL.

czlee commented 5 years ago

For what it's worth, all of the examples I posted above now work fine for me, as does the very first Example 1 (DataFrames) in the OP. So I wouldn't want to speak for others, but from my perspective this is now fixed. I'm now on Julia 1.1.1, Windows version 1809 build 17763.678.

OkonSamuel commented 5 years ago

I also use julia 1.1.1 but my windows version is 1803 and build is 17134.885

OkonSamuel commented 5 years ago

Maybe that's the reason I still see this error

OkonSamuel commented 5 years ago

Every thing works perfectly now after updating windows to version 1903 build 18362.295.

KristofferC commented 5 years ago

Perhaps we can close this then?

OkonSamuel commented 5 years ago

Yeah