Closed hustf closed 1 year ago
Minimal example with a clear cause - trying to access a non-existing drawing surface:
julia> begin
println(Threads.nthreads())
using Luxor
Drawing()
rotate(10*π/180)
end
12
PS C:\Users\f\.julia\environments\infinite_source> julia --project=.
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.8.3 (2022-11-14)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
julia> begin
println(Threads.nthreads())
using Luxor
rotate(10*π/180)
end
12
Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x3650875 -- cairo_rotate at /workspace/srcdir/cairo-1.16.0/src\cairo.c:1468
in expression starting at REPL[1]:1
cairo_rotate at /workspace/srcdir/cairo-1.16.0/src\cairo.c:1468
rotate at C:\Users\f\.julia\packages\Cairo\smWIA\src\Cairo.jl:680 [inlined]
rotate at C:\Users\f\.julia\dev\Luxor\src\basics.jl:607
unknown function (ip: 000001eefc735d2a)
jl_apply at C:/workdir/src\julia.h:1839 [inlined]
<....etc...>
Older versions of Luxor would give a nice warning:
(@oldLuxor) pkg> st
Status `C:\Users\f\.julia\environments\oldLuxor\Project.toml`
⌃ [ae8d54c2] Luxor v2.8.0 ⚲
Info Packages marked with ⌃ have new versions available and may be upgradable.
julia> begin
println(Threads.nthreads())
using Luxor
rotate(10*π/180)
end
12
ERROR: There is no current drawing.
Stacktrace:
[1] error(s::String)
@ Base .\error.jl:35
[2] get_current_cr()
@ Luxor C:\Users\f\.julia\packages\Luxor\XSNgj\src\drawings.jl:53
[3] rotate(a::Float64)
@ Luxor C:\Users\f\.julia\packages\Luxor\XSNgj\src\basics.jl:534
[4] top-level scope
@ REPL[2]:4
caused by: BoundsError: attempt to access 0-element Vector{Drawing} at index [1]
Stacktrace:
[1] getindex
@ .\array.jl:924 [inlined]
[2] get_current_cr()
@ Luxor C:\Users\frohu_h4g8g6y\.julia\packages\Luxor\XSNgj\src\drawings.jl:51
[3] rotate(a::Float64)
@ Luxor C:\Users\frohu_h4g8g6y\.julia\packages\Luxor\XSNgj\src\basics.jl:534
[4] top-level scope
@ REPL[2]:4
I believe Luxor.get_current_cr()
would be the place for an assertion?
Let's hope @oheil knows the answer! 😂
One proposal is
@assert c.ptr !== Ptr{Nothing}() "There is no current drawing context."
But that would need to be place outside of the current try..catch structure as an extra precation.
I don't want to use @assert
though. Manual says:
An assert might be disabled at various optimization levels. Assert should therefore only be used as a debugging tool
Looking into it.
Yes, a check needs to be there and, according to the MWE, it needs to break to flow:
function get_current_cr()
try
d=getfield(_current_drawing()[_current_drawing_index()], :cr)
if d.ptr == Ptr{Nothing}()
error("There is no current drawing.")
end
return d
catch
error("There is no current drawing.")
end
end
Ok, like that? PR incoming...
Wait, no, above is bad...
Actually this is the result of a remnant of SnoopPrecompile. I can't find out why there exists a Drawing remnant because if I do:
#include("precompile.jl")
in Luxor.jl, and do it manually in the REPL
include("precompile.jl")
there is no remnant and calling:
julia> using Luxor
[ Info: Precompiling Luxor [ae8d54c2-7ccd-5906-9d76-62fc9837b5bc]
julia> include("src\\precompile.jl")
[ Info: SnoopPrecompile is analyzing Luxor.jl code...
julia> cr=Luxor.get_current_cr()
ERROR: There is no current drawing.
is fine.
Perhaps because
Statements that occur inside a @precompile_all_calls block are executed only if the package is being actively precompiled; it does not run when the package is loaded,
Ok, anyways, if the Drawing is incomplete (CairoContext == C_NULL, CairoSurface == C_NULL) it must be initialized by call to Drawing(...).
This shows the remnant, because the buffer is intact:
julia> using Luxor
[ Info: Precompiling Luxor [ae8d54c2-7ccd-5906-9d76-62fc9837b5bc]
[ Info: SnoopPrecompile is analyzing Luxor.jl code...
julia> d=Luxor._current_drawing()[Luxor._current_drawing_index()]
Opens the "snooping away" PNG.
I don’t understand much of SnoopPrecompile, but I assumed that adding it would help performance. Perhaps it needs some more attention…
Me neither. Anyways it's an example where a corrupted Drawing remains as if it were fine. Luxor should be as defensive as possible to prevent bad pointers in Cairo. I am looking currently for the best place for a check.
The documentation has some advice on references to external libraries, pre_compilation and __init__()
. I read it from time to time. I also brush my teeth two times every day.
Some points there seem to fit. I will do this: 1) Making Luxor more robust for the general case 2) Find the specific caveat for SnoopPrecompile (like global IDs and/or Dicts...) 3) Update this thread with my findings 4) PR when ready 5) brushing my teeth
Skipped 3) PR is https://github.com/JuliaGraphics/Luxor.jl/pull/251
I wish you a Merry Christmas and a Happy New Year !!!
You too, great work that you do for the community lately! I'll mention it to the Christmas authorities.
Resolved in master. Issue can be closed after @hustf confirmed.
I'm trying to break this fix as hard as I can! It's not easy, but wait and see!
Perfect! No good software without extreme testing!
Make sure you only test @oheil's code then 😂😂😂
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Resolved in master. Issue should be closed. If anything happens it's better to create new issues. The existing issues are getting cluttered a bit.
This is a temporary issue / note. If crashes keep occuring, I'll post proper, reproducible code here or in Cairo.jl. The issue probably belongs elsewhere in the end. I do not believe this is the fault of the latest changes in master, though my function
encompass
is related to testing it.Crashes have occured three or five times in different circumstances while giving the latest master a whirl. As I was working in VSCode, the detailed errors were lost as Julia crashed. This time, I opened a REPL terminal in order to take notes and dump the output here.
I suspect the crashes are related to calling
getmatrix()
in very rapid succession. I'm not actually changing the matrix. I callgetmatrix()
in order to convert points to 'world coordinates'. It may be advisable to store the transformation matrix while mapping multiple points.Version info: