MakieOrg / Makie.jl

Interactive data visualizations and plotting in Julia
https://docs.makie.org/stable
MIT License
2.38k stars 302 forks source link

GLMakie: Error when running on headless server, assumes monitor #1802

Open maleadt opened 2 years ago

maleadt commented 2 years ago

When running on a headless server (with an X server and everything, but no active monitor), GLMakie errors when rendering a plot using save as follows:

ERROR: ArgumentError: cannot convert NULL to string
Stacktrace:
  [1] unsafe_string
    @ ./strings/string.jl:70 [inlined]
  [2] unsafe_string
    @ ./c.jl:193 [inlined]
  [3] GetMonitorName
    @ ~/Julia/depot/packages/GLFW/BWxfF/src/glfw3.jl:478 [inlined]
  [4] GLMakie.MonitorProperties(monitor::GLFW.Monitor)
    @ GLMakie ~/Julia/depot/packages/GLMakie/TfSB1/src/glwindow.jl:150
  [5] window_area(scene::Scene, screen::GLMakie.Screen)
    @ GLMakie ~/Julia/depot/packages/GLMakie/TfSB1/src/events.jl:50
  [6] register_callbacks(scene::Scene, native_window::GLMakie.Screen)
    @ Makie ~/Julia/depot/packages/Makie/lgPZh/src/interaction/events.jl:17
  [7] backend_display(screen::GLMakie.Screen, scene::Scene)
    @ GLMakie ~/Julia/depot/packages/GLMakie/TfSB1/src/display.jl:16
  [8] scene2image(scene::Scene)
    @ GLMakie ~/Julia/depot/packages/GLMakie/TfSB1/src/display.jl:33
  [9] backend_show(#unused#::GLMakie.GLBackend, io::IOContext{IOStream}, m::MIME{Symbol("image/png")}, scene::Scene)
    @ GLMakie ~/Julia/depot/packages/GLMakie/TfSB1/src/display.jl:41
 [10] show(io::IOContext{IOStream}, m::MIME{Symbol("image/png")}, scene::Scene)
    @ Makie ~/Julia/depot/packages/Makie/lgPZh/src/display.jl:109
 [11] (::Makie.var"#926#927"{Float64, Float64, DataType, Scene})(s::IOStream)
    @ Makie ~/Julia/depot/packages/Makie/lgPZh/src/display.jl:243
 [12] open(::Makie.var"#926#927"{Float64, Float64, DataType, Scene}, ::String, ::Vararg{String}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./io.jl:330
 [13] open
    @ ./io.jl:328 [inlined]
 [14] save(file::FileIO.File{FileIO.DataFormat{:PNG}, String}, fig::Scene; resolution::Tuple{Int64, Int64}, pt_per_unit::Float64, px_per_unit::Float64)
    @ Makie ~/Julia/depot/packages/Makie/lgPZh/src/display.jl:237
 [15] save(file::FileIO.File{FileIO.DataFormat{:PNG}, String}, fig::Scene)
    @ Makie ~/Julia/depot/packages/Makie/lgPZh/src/display.jl:222
 [16] save(filename::String, fig::Scene; args::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/Julia/depot/packages/Makie/lgPZh/src/display.jl:213
 [17] save
    @ ~/Julia/depot/packages/Makie/lgPZh/src/display.jl:213 [inlined]

While this should probably error properly, it could also be supported by using a fallback DPI when no monitor is connected.

fatteneder commented 2 years ago

I think for this you could use the xvfb-run script like it is done in the CI: https://github.com/JuliaPlots/GLMakie.jl/blob/8954fc34354a09ceb11159a8e8e35429c05a710f/.github/workflows/ci.yml#L41-L42

maleadt commented 2 years ago

That shouldn't be necessary; I'm actually running an X server, while xvfb starts a new one that isn't backed by the actual GPU I want to use. The problem is that GLMakie looks up the monitor, while there isn't one.