Segfault in ccall


#1

Here’s a minimal example:

julia> mutable struct FILE
       end

julia> outfile = ccall((:open, "libc"), Ptr{FILE}, (Cstring, Cstring), "test", "w+")
Ptr{FILE} @0xffffffffffffffff

julia> ccall((:fprintf, "libc"), Cuint, (Ptr{FILE}, Cstring), outfile, "write something")

signal (11): Segmentation fault: 11
while loading no file, in expression starting on line 0
flockfile at /usr/lib/system/libsystem_c.dylib (unknown line)
vfprintf_l at /usr/lib/system/libsystem_c.dylib (unknown line)
fprintf at /usr/lib/system/libsystem_c.dylib (unknown line)
anonymous at ./<missing> (unknown line)
jl_call_fptr_internal at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/./julia_internal.h:339 [inlined]
jl_call_method_internal at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/./julia_internal.h:358 [inlined]
jl_toplevel_eval_flex at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/toplevel.c:589
jl_toplevel_eval_in at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/builtins.c:496
eval at ./boot.jl:235
jlcall_eval_17976 at /Applications/Julia-0.6.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
eval_user_input at ./REPL.jl:66
jlcall_eval_user_input_20272 at /Applications/Julia-0.6.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
macro expansion at ./REPL.jl:97 [inlined]
#1 at ./event.jl:73
unknown function (ip: 0x11c63492f)
jl_apply at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/./julia.h:1424 [inlined]
start_task at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/task.c:267
Allocations: 1110321 (Pool: 1109185; Big: 1136); GC: 0
Segmentation fault: 11

It’s Julia 0.6 x86_64-apple-darwin13.4.0 release and this is run on macOS Sierra.

Does anyone know what might cause this and if there is a workaround for it? Thanks!


#2

AFAIK open takes a Cint for the second argument, not a string. The string version only works with the Julia function of the same name. Indeed, you can see that the pointer returned by the first call is not valid, it’s equal to -1 % UInt.


#3

Thanks for you reply. Sorry, that was a typo; I meant fopen. So here’s my actual error that I need help with:

The function signature for the C function I’m trying to call is

int Cudd_DumpDot (DdManager *dd, int n, DdNode **f, char const *const *inames, char const *const *onames, FILE *fp)

And here’s my code:

function output_dot(mgr::Ptr{Manager}, f::Ptr{Node}, filename::String)
    outfile = ccall((:fopen, "libc"), Ptr{FILE}, (Ptr{UInt8}, Ptr{UInt8}), "test", "w+")
    ccall((:Cudd_DumpDot, _LIB_CUDD), Void, (Ptr{Manager}, Cuint, Ptr{Ptr{Node}}, 
        Ptr{Ptr{UInt8}}, Ptr{Ptr{UInt8}}, Ptr{FILE}), mgr, 1, pointer_from_objref(f), C_NULL, C_NULL, outfile)
    ccall((:fclose, "libc"), Cuint, (Ptr{FILE},), outfile)
end

So when I called the function, I got

signal (11): Segmentation fault: 11
while loading no file, in expression starting on line 0
flockfile at /usr/lib/system/libsystem_c.dylib (unknown line)
vfprintf_l at /usr/lib/system/libsystem_c.dylib (unknown line)
fprintf at /usr/lib/system/libsystem_c.dylib (unknown line)
Cudd_DumpDot at /Users/zhao/.julia/v0.6/CUDD/deps/cudd-3.0.0/cudd/.libs/libcudd-3.0.0.0.dylib (unknown line)
output_dot at /Users/zhao/.julia/v0.6/CUDD/src/ADD.jl:87
unknown function (ip: 0x119239d33)
do_call at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/interpreter.c:75
eval at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/interpreter.c:242
jl_interpret_toplevel_expr at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/interpreter.c:34
jl_toplevel_eval_flex at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/toplevel.c:577
jl_toplevel_eval_in at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/builtins.c:496
eval at ./boot.jl:235
jlcall_eval_17976 at /Applications/Julia-0.6.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
eval_user_input at ./REPL.jl:66
jlcall_eval_user_input_20272 at /Applications/Julia-0.6.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
macro expansion at ./REPL.jl:97 [inlined]
#1 at ./event.jl:73
unknown function (ip: 0x11922c92f)
jl_apply at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/./julia.h:1424 [inlined]
start_task at /Users/osx/buildbot/slave/package_osx10_9-x64/build/src/task.c:267
Allocations: 1025905 (Pool: 1024796; Big: 1109); GC: 0
Segmentation fault: 11

So I was wondering if there is any place that I didn’t write properly?


#4

First, as Keno mentioned in the github issue, have you checked the return value for error?

Also in general you should use Cstring instead of Ptr{UInt8} for, well, C strings and you don’t need the "libc". These shouldn’t be the issue here though.

In general, unless you are always manually managing the C objects, you must not pass bare pointers to ccall. Instead you should define the appropriate cconvert and unsafe_convert (you can find how to use them in the doc).
Also, you should never use pointer_from_objref as ccall arguments especially not on an isbit object, semantically the return value is invalid as soon as the function returns. Use Ref{Ptr{...}} as argument type if you really need a pointer to the pointer.

It’s impossible to tell if other parameters are passed correctly (other than the possible issues mentioned above) but the handling of FILE* shouldn’t have any problems. The following works for me.

julia> ccall(:fopen, Ptr{Void}, (Cstring, Cstring), "test", "w+")
Ptr{Void} @0x0000000002407460

julia> fptr = ans
Ptr{Void} @0x0000000002407460

julia> ccall(:fprintf, Cint, (Ptr{Void}, Cstring), fptr, "write something")
15

julia> ccall(:fclose, Cint, (Ptr{Void},), fptr)
0

shell> cat test
write something

#5

If I use Ref{Ptr{...}} as the argument type, then what do I pass as an argument for f?


#6

f