Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault when reinterpreting in a for loop #20847

Closed
fredrikekre opened this issue Mar 1, 2017 · 4 comments · Fixed by #22066
Closed

Segfault when reinterpreting in a for loop #20847

fredrikekre opened this issue Mar 1, 2017 · 4 comments · Fixed by #22066
Labels
bug Indicates an unexpected problem or unintended behavior types and dispatch Types, subtyping and method dispatch
Milestone

Comments

@fredrikekre
Copy link
Member

Found this in https://github.com/KristofferC/JuAFEM.jl/pull/123 on all nightly build bots. Reduced to the following MRE:

function segfaultfunction{N, T}(A::Vector{NTuple{N, T}})
    B = reinterpret(T, A, (N, length(A)))
    return nothing
end

tuplevec = Tuple{Float64, Float64}[(0.0,0.0), (1.0,0.0)]

for A in (1,)
    segfaultfunction(tuplevec)
end

Pasting this in the REPL gives:

signal (4): Illegal instruction
while loading no file, in expression starting on line 0
macro expansion at ./REPL[3]:2 [inlined]
anonymous at ./<missing> (unknown line)
jl_call_method_internal at /home/fredrik/julia-master/src/julia_internal.h:248 [inlined]
jl_toplevel_eval_flex at /home/fredrik/julia-master/src/toplevel.c:589
jl_toplevel_eval_in at /home/fredrik/julia-master/src/builtins.c:484
eval at ./boot.jl:235
unknown function (ip: 0x7ff385ed745f)
jl_call_method_internal at /home/fredrik/julia-master/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/fredrik/julia-master/src/gf.c:2212
eval_user_input at ./REPL.jl:66
unknown function (ip: 0x7ff176788ac6)
jl_call_method_internal at /home/fredrik/julia-master/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/fredrik/julia-master/src/gf.c:2212
macro expansion at ./REPL.jl:97 [inlined]
#1 at ./event.jl:73
unknown function (ip: 0x7ff176782eff)
jl_call_method_internal at /home/fredrik/julia-master/src/julia_internal.h:248 [inlined]
jl_apply_generic at /home/fredrik/julia-master/src/gf.c:2212
jl_apply at /home/fredrik/julia-master/src/julia.h:1410 [inlined]
start_task at /home/fredrik/julia-master/src/task.c:261
unknown function (ip: 0xffffffffffffffff)
Allocations: 3330816 (Pool: 3329230; Big: 1586); GC: 4
Illegal instruction (core dumped)

The following functions also segfaults:

function segfaultfunction{T}(A::Vector{Tuple{T, T}})
    B = reinterpret(T, A, (2, length(A)))
    return nothing
end

function segfaultfunction{N}(A::Vector{NTuple{N, Float64}})
    B = reinterpret(Float64, A, (N, length(A)))
    return nothing
end

but this one (without any paremeters N or T) works

function no_segfaultfunction(A::Vector{Tuple{Float64, Float64}})
    B = reinterpret(Float64, A, (2, length(A)))
    return nothing
end
  • It should also be noted that this only segfaults if the for-loop is there.
  • If tuplevec is defined inside the for-loop it doesn't segfault (same mechanism as if the for-loop wouldn't be there I guess)
  • The reinterpret inside the function is successful, e.g. @show B before returning works

Perhaps related to #17003 but the examples in this issue all work on 0.5 so I figured this might be another issue.

@KristofferC
Copy link
Member

KristofferC commented Mar 1, 2017

It looks similar to #17003 because putting the loop in a function, llvm says (note the trap):

julia> @code_llvm f()

define void @julia_f_67597() #0 !dbg !5 {
pass:
  %ptls_i8 = call i8* asm "movq %fs:0, $0;\0Aaddq $$-10896, $0", "=r,~{dirflag},~{fpsr},~{flags}"() #5
  %ptls = bitcast i8* %ptls_i8 to i8****
  %0 = alloca [4 x i8**], align 8
  %.sub = getelementptr inbounds [4 x i8**], [4 x i8**]* %0, i64 0, i64 0
  %1 = getelementptr [4 x i8**], [4 x i8**]* %0, i64 0, i64 2
  %2 = bitcast i8*** %1 to i8*
  call void @llvm.memset.p0i8.i32(i8* %2, i8 0, i32 16, i32 8, i1 false)
  %3 = bitcast [4 x i8**]* %0 to i64*
  store i64 4, i64* %3, align 8
  %4 = getelementptr [4 x i8**], [4 x i8**]* %0, i64 0, i64 1
  %5 = bitcast i8* %ptls_i8 to i64*
  %6 = load i64, i64* %5, align 8
  %7 = bitcast i8*** %4 to i64*
  store i64 %6, i64* %7, align 8
  store i8*** %.sub, i8**** %ptls, align 8
  %8 = getelementptr [4 x i8**], [4 x i8**]* %0, i64 0, i64 3
  %9 = load i64, i64* inttoptr (i64 139902940366696 to i64*), align 8
  %10 = bitcast i8*** %8 to i64*
  store i64 %9, i64* %10, align 8
  store i8** inttoptr (i64 139902937612592 to i8**), i8*** %1, align 8
  %11 = call i8** @jl_apply_generic(i8*** %1, i32 2)
  call void @llvm.trap()
  unreachable
}

@yuyichao
Copy link
Contributor

yuyichao commented Mar 1, 2017

This isn't #17003 but is also an inference error. The loop can be replaced with a function and is just a way to trigger type inference.

julia> function segfaultfunction{N, T}(A::Vector{NTuple{N, T}})
           B = reinterpret(T, A, (N, length(A)))
           return nothing
       end
segfaultfunction (generic function with 1 method)

julia> code_warntype(segfaultfunction, Tuple{Any})
Variables:
  #self#::#segfaultfunction
  A::Array{Tuple{Vararg{T,N}},1} where T where N
  B::Any

Body:
  begin
      B::Any = (Main.reinterpret)($(Expr(:static_parameter, 2)), A::Array{Tuple{Vararg{T,N}},1} where T where N, (Core.tuple)($(Expr(:static_parameter, 1)), (Base.arraylen)(A::Array{Tuple{Vararg{T,N}},1} where T where N)::Int64)::Tuple{Any,Int64})::Union{} # line 3:
  end::Union{}

@yuyichao yuyichao added bug Indicates an unexpected problem or unintended behavior compiler:inference Type inference labels Mar 1, 2017
@vtjnash vtjnash added types and dispatch Types, subtyping and method dispatch and removed compiler:inference Type inference labels Mar 7, 2017
@vtjnash
Copy link
Member

vtjnash commented Mar 7, 2017

The problem is in type-intersection-env: the static-parameter 2 value is not correctly expressed, leading to an ambiguity about whether it is actually Tuple{Vararg{T,N}} where T where N (as given here) or Tuple{Vararg{T,N}} where N (where the bound on T is outside the result expression).

julia> Base._methods(reinterpret, (Any, Array{Tuple{Vararg{T,N}},1} where T where N, Tuple{Any,Int64}), -1, typemax(UInt64))
1-element Array{Any,1}:
svec(Tuple{Base.#reinterpret,Type{T},Array{Tuple{Vararg{T,N}},1} where T where N,Tuple{Int64,Int64}} where T, svec(T, Tuple{Vararg{T,N}} where T where N, 2), reinterpret(::Type{T}, a::Array{S,N} where N, dims::Tuple{Vararg{Int64,N}}) where {T, S, N} in Base at array.jl:142)

This leads type-inference to conclude that it should replace the call isbits(Tuple{Vararg{T,N}} where T where N)) with the constant false.

@vtjnash vtjnash mentioned this issue Mar 7, 2017
53 tasks
@JeffBezanson JeffBezanson added this to the 0.6.x milestone Apr 4, 2017
@KristofferC
Copy link
Member

Still crashes with newest master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants