JuliaGizmos / Blink.jl

Web-based GUIs for Julia
Other
360 stars 75 forks source link

test Blink fails - ERROR: LoadError: IOError: connect: connection refused (ECONNREFUSED) #325

Open ajdavid opened 2 months ago

ajdavid commented 2 months ago

Problems appeared with PlotlyJS after upgrading my OS to Ubuntu 24.04 LTS Testing isolated the issue to Blink

This works:

julia> Blink.AtomShell.electron() "/home/adavid/.julia/artifacts/aad3f721351c9550129f625fc52f51f4d0726586/electron"

However, the below test does not. I was running a built 1.12.x environment when I encountered the error. Reverted to 1.10.3, but did not resolve the issue.

What can I do to help track down the root cause? Note that VSCode (electron app) works OK.

() | Documentation: https://docs.julialang.org () | () () | | | | Type "?" for help, "]?" for Pkg help. | | | | | | |/ ` | | | | || | | | (| | | Version 1.10.3 (2024-04-30) / |_'|||_'_| |
|
/ |

julia> using Blink

(@v1.10) pkg> test Blink Testing Blink Status /tmp/jl_Ll68X4/Project.toml [ad839575] Blink v0.12.9 [cd3eb016] HTTP v1.10.8 [97c1335a] JSExpr v0.5.4 [682c06a0] JSON v0.21.4 [50d2b5c4] Lazy v0.15.1 [1914dd2f] MacroTools v0.5.13 [ffc61752] Mustache v1.0.19 [a975b10e] Mux v1.0.2 [189a3867] Reexport v1.2.2 [0f1e0344] WebIO v0.8.21 [2a0f44e3] Base64 [8ba89e20] Distributed [56ddb016] Logging [44cfe95a] Pkg v1.10.0 [6462fe0b] Sockets [8dfed614] Test Status /tmp/jl_Ll68X4/Manifest.toml [bf4720bc] AssetRegistry v0.1.0 [d1d4a3ce] BitFlags v0.1.9 [ad839575] Blink v0.12.9 [944b1d66] CodecZlib v0.7.5 [3da002f7] ColorTypes v0.11.5 [5ae59095] Colors v0.12.11 [f0e56b4a] ConcurrentUtilities v2.4.2 [9a962f9c] DataAPI v1.16.0 [e2d170a0] DataValueInterfaces v1.0.0 [460bff9d] ExceptionUnwrapping v0.1.10 [53c48c17] FixedPointNumbers v0.8.5 [de31a74c] FunctionalCollections v0.5.0 [cd3eb016] HTTP v1.10.8 [9fb69e20] Hiccup v0.2.2 [82899510] IteratorInterfaceExtensions v1.0.0 [692b3bcd] JLLWrappers v1.5.0 [97c1335a] JSExpr v0.5.4 [682c06a0] JSON v0.21.4 [50d2b5c4] Lazy v0.15.1 [e6f89c97] LoggingExtras v1.0.3 [1914dd2f] MacroTools v0.5.13 [739be429] MbedTLS v1.1.9 [ffc61752] Mustache v1.0.19 [a975b10e] Mux v1.0.2 [510215fc] Observables v0.5.5 [4d8831e6] OpenSSL v1.4.3 [bac558e1] OrderedCollections v1.6.3 [69de0a69] Parsers v2.8.1 [fa939f87] Pidfile v1.3.0 [aea7be01] PrecompileTools v1.2.1 [21216c6a] Preferences v1.4.3 [189a3867] Reexport v1.2.2 [ae029012] Requires v1.3.0 [777ac1f9] SimpleBufferStream v1.1.0 [3783bdb8] TableTraits v1.0.1 [bd369af6] Tables v1.11.1 [3bb67fe8] TranscodingStreams v0.11.0 [5c2747f8] URIs v1.5.1 [0f1e0344] WebIO v0.8.21 [104b5d7c] WebSockets v1.6.0 [cc8bc4a8] Widgets v0.6.6 [458c3c95] OpenSSL_jll v3.0.14+0 [0dad84c5] ArgTools v1.1.1 [56f22d72] Artifacts [2a0f44e3] Base64 [ade2ca70] Dates [8ba89e20] Distributed [f43a241f] Downloads v1.6.0 [7b1f6079] FileWatching [b77e0a4c] InteractiveUtils [b27032c2] LibCURL v0.6.4 [76f85450] LibGit2 [8f399da3] Libdl [37e2e46d] LinearAlgebra [56ddb016] Logging [d6f4376e] Markdown [a63ad114] Mmap [ca575930] NetworkOptions v1.2.0 [44cfe95a] Pkg v1.10.0 [de0858da] Printf [3fa0cd96] REPL [9a3f8284] Random [ea8e919c] SHA v0.7.0 [9e88b42a] Serialization [6462fe0b] Sockets [2f01184e] SparseArrays v1.10.0 [10745b16] Statistics v1.10.0 [fa267f1f] TOML v1.0.3 [a4e569a6] Tar v1.10.0 [8dfed614] Test [cf7118a7] UUIDs [4ec0a83e] Unicode [e66e0078] CompilerSupportLibraries_jll v1.1.1+0 [deac9b47] LibCURL_jll v8.4.0+0 [e37daf67] LibGit2_jll v1.6.4+0 [29816b5a] LibSSH2_jll v1.11.0+1 [c8ffd9c3] MbedTLS_jll v2.28.2+1 [14a3606d] MozillaCACerts_jll v2023.1.10 [4536629a] OpenBLAS_jll v0.3.23+4 [bea87d4a] SuiteSparse_jll v7.2.1+1 [83775a58] Zlib_jll v1.2.13+1 [8e850b90] libblastrampoline_jll v5.8.0+1 [8e850ede] nghttp2_jll v1.52.0+1 [3f19e933] p7zip_jll v17.4.0+2 Testing Running tests... ERROR: LoadError: IOError: connect: connection refused (ECONNREFUSED) Stacktrace: [1] wait_connected(x::TCPSocket) @ Sockets ~/Projects/julia/usr/share/julia/stdlib/v1.10/Sockets/src/Sockets.jl:528 [2] connect @ ~/Projects/julia/usr/share/julia/stdlib/v1.10/Sockets/src/Sockets.jl:563 [inlined] [3] connect(addr::IPv4, port::Int64) @ Sockets ~/Projects/julia/usr/share/julia/stdlib/v1.10/Sockets/src/Sockets.jl:549 [4] try_connect(::IPv4, ::Vararg{Any}; interval::Float64, attempts::Int64) @ Blink.AtomShell ~/.julia/packages/Blink/tnO3a/src/AtomShell/process.jl:77 [5] try_connect @ ~/.julia/packages/Blink/tnO3a/src/AtomShell/process.jl:74 [inlined] [6] init(; debug::Bool) @ Blink.AtomShell ~/.julia/packages/Blink/tnO3a/src/AtomShell/process.jl:91 [7] init @ ~/.julia/packages/Blink/tnO3a/src/AtomShell/process.jl:85 [inlined] [8] #shell#6 @ ~/.julia/packages/Blink/tnO3a/src/AtomShell/process.jl:147 [inlined] [9] shell @ ~/.julia/packages/Blink/tnO3a/src/AtomShell/process.jl:138 [inlined] [10] #Window#11 @ ~/.julia/packages/Blink/tnO3a/src/AtomShell/window.jl:100 [inlined] [11] top-level scope @ ~/.julia/packages/Blink/tnO3a/test/runtests.jl:3 [12] include(fname::String) @ Base.MainInclude ./client.jl:489 [13] top-level scope @ none:6 in expression starting at /home/adavid/.julia/packages/Blink/tnO3a/test/runtests.jl:3 ERROR: Package Blink errored during testing

pfitzseb commented 2 months ago

Does the issue persist over re-runs of the tests? I'm pretty sure we're trying a random port each time, so tests will fail if we hit one in use on your machine.

ajdavid commented 2 months ago

Unfortunately, it does persist. I must have run Blink.Window() over 20 times while testing it. I just ran it another 10 times. Same result.

ajdavid commented 2 months ago

Just for certainty, I installed Ubuntu 23.10.1 on gnome-boxes. Installed Julia 1.10 and added Blink. test Blink passed all tests. Oracle Linux 9 on gnome-boxes: test Blink worked. Ubuntu 24.04 on gnome-boxes: test Blink failed (in case it was something in my desktop configuration)

ujimushi commented 2 months ago

Sorry. I can only speak Japanese, so I will translate it into English using Google Translate.

Since Ubuntu version 24.04, apparmor restrictions have become stricter, so there are restrictions on starting executable files other than apps installed using apt or snap.

On Ubuntu24.04, if you run /home/adavid/.julia/artifacts/aad3f721351c9550129f625fc52f51f4d0726586/electron from the shell, you should not be able to execute it due to an error.

As per my Japanese blog post, the simplest solution is to add the --no-sandbox option when running electron.

If you want to achieve this without modifying Blink.jl module, you can rewrite the init function, for example, as follows.


using Blink

@eval AtomShell begin
    function init(; debug = false)
        electron() # Check path exists
        p, dp = port(), port()
        debug && inspector(dp)
        dbg = debug ? "--debug=$dp" : []
        proc = (debug ? run_rdr : run)(
            `$(electron()) --no-sandbox $dbg $mainjs port $p`; wait=false)
        conn = try_connect(ip"127.0.0.1", p)
        shell = Electron(proc, conn)
        initcbs(shell)
        return shell
    end
end

After running the above code, win = Window() should work fine.

I think this problem only occurs on Ubuntu 24.04.

ajdavid commented 2 months ago

Workaround confirmed successful on Ubuntu 24.04

pfitzseb commented 2 months ago

I wouldn't recommended disabling Chromium's sandboxing globally, especially if there's a chance you can end up on an untrusted website (ref https://www.electronjs.org/docs/latest/tutorial/sandbox#disabling-chromiums-sandbox-testing-only).

Relevant upstream issue: https://github.com/electron/electron/issues/41066, https://github.com/microsoft/vscode/issues/202965

We can implement a env var check (e.g. JULIA_BLINK_NO_ELECTRON_SANDBOX) for this, but hopefully the issue gets resolved upstream at some point too...

ujimushi commented 2 months ago

If you're concerned about security, here are some options.

using Blink

function make_electron_profile(filename)
    text = """
    abi <abi/4.0>,

    include <tunables/global>

    $(Blink.AtomShell.electron()) flags=(unconfined) {
      userns,

    # Site-specific additions and overrides. See local/README for details.
        include if exists <local/electron>
    }
    """
    open(filename, "w") do io
        print(io, text)
    end
    println("copy to /etc/apparmore.d/")
end

After running the above code, create a profile as follows.

make_electron_profile("my_blink_electron")

Next, copy the profile you created to /etc/apparmore.d/.

sudo cp my_blink_electron /etc/apparmore.d/

Then, when you restart your PC, you should be able to execute win = Window() without any special changes to the source.

However, if the electron binary changes, the profile also needs to be changed.