Skip to content

Unrooted type pointer literal from cfunction #47029

Open

Description

Reduced from FunctionWrappers example to the code below.

f(a) = a .+ 1

const AT = Union{Vector{Int},Vector{Float64}}

function gen_fptr(::Type{T}) where {T}
    @cfunction(f, Ref{AT}, (Ref{AT},))
end
fptr = gen_fptr(Int)
# @show fptr
# ccall(:jl_breakpoint, Cvoid, (Ptr{Cvoid},), fptr)

ccall(fptr, Ref{AT}, (Ref{AT},), [1])
println(1)

GC.gc()

ccall(fptr, Ref{AT}, (Ref{AT},), [1])

The first ccall should complete without much issue but the GC call causes the second ccall to refer to a dangling pointer which may either throw a non-sense type error or just crash while trying to throw that error.

During codegen of gen_fptr. emit_cfunction added a UnionAll wrapper on the return type Ref{AT}. This got passed down to the emit_typecheck call in gen_cfunc_wrapper without any further processing. This type then bypasses the union type check optimization in emit_isa, which should only be a performance issue and not a correctness one, before finally get embedded in the code without being rooted anywhere.

It seems that some optimizations could be added to hide this issue. However, I assume it's the callers responsibility to root the argument to emit_typecheck/emit_isa. In fact, emit_cfunction does root rt but never the wrapped declrt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions