Module causing Julia to hang when compiling simple function

question

#1

Hi all,

Julia v0.5 on Ubuntu 16.04. When working in the REPL, I run the following two lines

using MyModule
f() = error("argh")

The first line runs fine, but the second line hangs, ie I just get a flashing cursor and have to end the process externally via the system monitor. I’m guessing there is a bug in MyModule, since the second line is fairly innocuous, but I’m not really sure what I should be looking for (there are no error message since, as stated, julia appears to get stuck in some sort of infinite loop).

But here is where it gets weird. If I do this (pressing Enter between each line):

f() = error("argh")
using MyModule
f() = error("argh")

everything works fine (although obviously I get the warning message about f() being overwritten). Even weirder though, if I do this:

f() = error("argh") ; using SDatas ; f() = error("argh")

ie evaluate all three statements in one line with only one press of Enter, then I get the warning message, but then julia hangs (flashing cursor) and has to be externally ended.

As stated, there is obviously something wrong in MyModule, but it is a fairly large module and I was hoping someone might be able to provide some clues as to where in this module I should be looking for the source of the problem.

Cheers and thanks in advance for any/all help,

Colin


#2

Are you overloading Base.error in MyModule? Given the ordering, it could be a method table issue. If either MyModule or SDatas are open-source someone might be able to take a look. Otherwise you will have to either make a case reduction or jump in gdb/lldb and see what the process is doing while it hangs.


#3

Thanks for responding. I don’t overload Base.error, but I do extend several other methods from Base, plus the module also has quite a few other imports and exports to various modules. So I agree it could definitely be a method table issue. I’ll start looking into that.

Are you able to point me towards any reading on “case reduction” and “gdb/lldb” - I’m afraid I don’t actually know what these things are. I don’t want to waste your time though, so I’m happy to read through the docs if you can give me some idea as to which section is the appropriate one.

Cheers and thanks,

Colin


#4

UPDATE: Couldn’t find anything wrong with the method table, so I bit the bullet and went through the module commenting out blocks to try and track down the offending piece of code. It turns out to be just one line, which follows:

Base.in{T1, T2}(s::SData{T1, T2}, y::T1)::Bool = in(i, s.inds)

As you can see, I’m extending Base.in here for my own custom type SData. Note that up the front my module includes the following line:

import Base:    intersect, union, in, hcat, vcat

None of my other extensions from Base seem to have any trouble. Is it possible that there is something unusual about the in function, perhaps to do with the fact that it has its own special syntactic rules eg in iterators. That is, do I need to do something different to the usual rules if I want to extend in?

Cheers and thanks,

Colin


#5

Small reproducing example; the response in your second message is close –

The other thing that would help is a definition for SData that reproduces the problem (field names changed if necessary, etc.).

That said, there’s a fairly good chance this is fixed on 0.6-dev, so I would suggest also testing on a very recent nightly (if your code runs there without too much trouble).

Sorry, gdb and lldb are debuggers, which would be able to interrupt execution and probably show a stack trace of the current process state.


#6

I don’t know what SData is, but if it is a collection, are you sure it is meant to be the 1st argument of in, which usually has the signature in(item, collection)?


#7

Yes, I just noticed this myself as I posted the code (I wrote that line just after extending the dequeues where (collection, item) is the standard). I’ll swap them round once I solve the issue discussed in my original post.

Cheers,

Colin


#8

Now that I’ve isolated the line, I’ll see if I can put together a small reproducing example as you suggest, although it may be a bit tricky since in is actually imported into a few other modules that the SDatas module depends on in my code. I’ll post back here when I’m done. Thanks for your help.

Cheers,

Colin


#9

Okay, I’ve got the reproducible example. And it is weird!

module TestModule1
import Base:    in
export  TestType1
type TestType1{T}
    inds::Vector{T}
end
Base.in{T}(x::TestType1{T}, y::T) = in(i, x.inds)
end

If I place the following module somewhere on LOAD_PATH, I can then run the following two lines:

using TestModule1
f() = "argh"

And Julia hangs indefinitely on the second line. But, notice that TestModule1 contains an error. I’ve written in(i, x.inds), where I should have written in(y, x.inds). If I change the i to a y, then everything runs fine, and Julia no longer hangs on f() = "argh". Note that if I fire up a new instance of Julia and type i, I get ERROR: UndefVarError: i not defined, so the issue is not that i is somehow already linked to something else.

I don’t have v0.6, and last time I tried to run two versions side-by-side I managed to mess it up. Can someone who is running the latest v0.6 use my TestModule1 above to check whether this problem still exists on v0.6? If so, please let me know and I’m happy to file an issue.

Cheers,

Colin


#10

Yes, hang still happens on 0.6, even simply pasting the module definition into the REPL. However, if I comment out the Base.in line, execute the module block, and then uncomment and re-execute the block, there is no hang. Please do open an issue.


#11

Seems to be a really deep/infinite loop/recursion in subtype.c


#12

Done. Issue #20267.

Thanks for your help.

Cheers,

Colin


#13

Thanks for looking into it. I’ve added that information to issue #20267 on github