Can a FunctionWrapper be used with a function that isn't type stable?

I’ve been experimenting with using FunctionWrappers.jl. When I try to create a FunctionWrapper for a function that doesn’t have a stable return type, I get a segfault. Is that a limitation of FunctionWrapper, or is that a bug?

Here’s a simple example:

julia> using FunctionWrappers

julia> f = FunctionWrappers.FunctionWrapper{Any,Tuple{Int}}((x) -> iseven(x) ? 2.0 : 1)
FunctionWrappers.FunctionWrapper{Any,Tuple{Int64}}(Ptr{Nothing} @0x00000001221b7010, Ptr{Nothing} @0x00000001125fc390, Base.RefValue{getfield(Main, Symbol("##3#4"))}(getfield(Main, Symbol("##3#4"))()), getfield(Main, Symbol("##3#4")))

julia> f(1)

signal (11): Segmentation fault: 11
in expression starting at no file:0
unknown function (ip: 0x1221b70d0)
macro expansion at /Users/dmatz/.julia/packages/FunctionWrappers/mJrYu/src/FunctionWrappers.jl:111 [inlined]
do_ccall at /Users/dmatz/.julia/packages/FunctionWrappers/mJrYu/src/FunctionWrappers.jl:102 [inlined]
FunctionWrapper at /Users/dmatz/.julia/packages/FunctionWrappers/mJrYu/src/FunctionWrappers.jl:118
unknown function (ip: 0x1221ba966)
jl_fptr_trampoline at /Users/osx/buildbot/slave/package_osx64/build/src/gf.c:1864
do_call at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:323
eval_stmt_value at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:362 [inlined]
eval_body at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:759
jl_interpret_toplevel_thunk_callback at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:885
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x11488e3af)
unknown function (ip: 0xffffffffffffffff)
jl_interpret_toplevel_thunk at /Users/osx/buildbot/slave/package_osx64/build/src/interpreter.c:894
jl_toplevel_eval_flex at /Users/osx/buildbot/slave/package_osx64/build/src/toplevel.c:764
jl_toplevel_eval at /Users/osx/buildbot/slave/package_osx64/build/src/toplevel.c:773 [inlined]
jl_toplevel_eval_in at /Users/osx/buildbot/slave/package_osx64/build/src/toplevel.c:793
eval at ./boot.jl:328
eval_user_input at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/REPL/src/REPL.jl:85
macro expansion at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.1/REPL/src/REPL.jl:117 [inlined]
#26 at ./task.jl:259
jl_apply at /Users/osx/buildbot/slave/package_osx64/build/src/./julia.h:1571 [inlined]
start_task at /Users/osx/buildbot/slave/package_osx64/build/src/task.c:572
Allocations: 1516561 (Pool: 1516252; Big: 309); GC: 2
Segmentation fault: 11

Yes it should be supported and yes this seems like a julia bug.

Exact case

julia> f(x) = x ? 1 : 2.0
f (generic function with 1 method)

julia> g(f, x) = f(x)
g (generic function with 1 method)

julia> gptr = @cfunction(g, Any, (Ref{typeof(f)}, Bool,))
Ptr{Nothing} @0x00007fed90fec7e0

julia> ccall(gptr, Any, (Any, Bool,), f, true)

signal (11): Segmentation fault

Or

julia> f(x) = x ? 1 : 2.0
f (generic function with 1 method)

julia> g(f, x) = f(x)
g (generic function with 1 method)

julia> gptr = @cfunction(g, Any, (Ref{typeof(f)}, Bool,))
Ptr{Nothing} @0x00007fa0fed4b7e0

julia> ccall(gptr, Any, (Ref{typeof(f)}, Bool,), f, true)

signal (11): Segmentation fault

Simplified case,

julia> f(x) = x ? 1 : 2.0
f (generic function with 1 method)

julia> fptr = @cfunction(f, Any, (Bool,))
Ptr{Nothing} @0x00007effcbe85e00

julia> ccall(fptr, Any, (Bool,), true)
Unreachable reached at 0x7effcbe85f2a

signal (4): Illegal instruction
1 Like

I created an issue:

https://github.com/JuliaLang/julia/issues/32251

3 Likes