Crystal: Segfault issue

Created on 15 Oct 2017  路  5Comments  路  Source: crystal-lang/crystal

I'm currently working on an open source project and I face a segfault issue in my specs; this bug happens pseudo-randomly, as changing the order of the specs would lead to success or crashing of the test-case.

I tried to "isolate" the issue for hours, and managed to clear some features which are known to be buggy (e.g.
method missing) but I cannot figure out what's wrong here.

Sadly I'm not able to paste here a small reproductible code, however I have full reproductible case of the bug in the full library.

Since it's an open source / on my free time project, I just commited it on github here:

https://github.com/anykeyh/clear

Thankfully the event is fully reproduceable:

To make it crash (see stacktrace below)
crystal run spec/sql/select.cr

To make it behave strangely. Here it won't crash but the spec will fail with "random" data (a date where an array is pushed in parameters)
crystal run --release spec/sql/select.cr

If you change the order of the spec in the source code, it will not crash anymore. Or it will. Well, it depends of the order of the spec...

PS: I've made a branch "segfault" to keep track of the buggy code, in case I continue to develop on it.

Additional informations:

Stacktrace

Invalid memory access (signal 11) at address 0x10401d000
[0x103daa11b] *CallStack::print_backtrace:Int32 +107
[0x103d8d7cc] __crystal_sigfault_handler +60
[0x7fffa857db3a] _sigtramp +26
[0x103dc068c] *Pointer(UInt8)@Pointer(T)#[]<Int32>:UInt8 +28
[0x103db1bc3] *String#unsafe_byte_at<Int32>:UInt8 +35
[0x103dd51de] *Char::Reader#byte_at<Int32>:UInt32 +30
[0x103dd4674] *Char::Reader#decode_current_char:Char +36
[0x103dd61fa] *Char::Reader#next_char:Char +58
[0x103db5093] *String#inspect<String::Builder>:String::Builder +371
[0x103db4f02] *String@Object#inspect:String +66
[0x103db9679] *String#pretty_print<PrettyPrint>:(Int32 | Nil) +25
[0x103e2a194] *PrettyPrint::format<(String | Nil), IO::FileDescriptor, Int32, String, Int32>:IO::FileDescriptor +212
[0x103e2a0ad] *PrettyPrint::format<(String | Nil), IO::FileDescriptor, Int32>:IO::FileDescriptor +61
[0x103d90842] *p<(String | Nil)>:(String | Nil) +34
[0x103e1f15f] *Clear::SQL::SelectQuery#to_sql:String +127
[0x103d94de4] ~procProc(Nil)@spec/sql/select.cr:228 +548
[0x103d9115b] *it<String, String, Int32, Int32, &Proc(Nil)>:(Array(Spec::Result) | Nil) +379
[0x103d93a50] ~procProc(Nil)@spec/sql/select.cr:160 +656
[0x103dfb872] *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ +354
[0x103d91f53] *describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ +51
[0x103d937b3] *context<String, String, Int32, &Proc(Nil)>:Spec::Context+ +51
[0x103d92a92] ~procProc(Nil)@spec/sql/select.cr:118 +162
[0x103dfb872] *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ +354
[0x103d91f53] *describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ +51
[0x103d905dd] ~procProc(Nil)@spec/sql/select.cr:26 +397
[0x103dfb872] *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ +354
[0x103d91f53] *describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ +51
[0x103d9043b] ~procProc(Nil)@spec/sql/select.cr:25 +107
[0x103dfb872] *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ +354
[0x103d91f53] *describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ +51
[0x103d79843] __crystal_main +3907
[0x103d8d6c8] main +40

Weird output in --release mode :

  1) Clear::SQL SelectQuery the WHERE clause using expression engine can check presence into array
     Failure/Error: r.to_sql.should eq "SELECT *\nFROM users\nWHERE users.id IN (1, 2, 3, 4)"

       Expected: "SELECT *\nFROM users\nWHERE users.id IN (1, 2, 3, 4)"
            got: "SELECT *\nFROM users\nWHERE '0001-01-01 00:0711.962'"

     # spec/sql/select.cr:231

there's typo in date format, however (07:11.962 = 431.962 seconds just fyi)

bug compiler topicgenerics topicsemantic

All 5 comments

You are using generic class inheritance. That's probably the reason for the segfault.

I see you don't use Collection(T), so removing that is the first step. Then you can try to change Literal(T) to not be generic, just Literal. This is just for a test. Then you can see if the code runs without segfaults.

It the segfault still happens, report back. Otherwise, I'm sure this is a duplicate of one of the existing bugs related to generic types and inheritance.

(I don't have time to try this today)

I just tried it with this (it took me 1 minute):

class Clear::Expression::Node::Literal < Clear::Expression::Node
  def initialize(@lit : Bool | Int32 | String | Time)
  end

  def resolve
    Clear::Expression[@lit]
  end
end

The segfault is gone.

Maybe a duplicate of https://github.com/crystal-lang/crystal/issues/3299

But generally related to https://github.com/crystal-lang/crystal/issues/2665

I might try to fix this (maybe not very hard) but I can't promise anything. My only advice is to avoid generic inheritance for now.

Why is this closed?

@straight-shoota I think he gave up on Crystal because of bugs that never get fixed. That happens to me sometimes.

I closed it because:

  • It lacked of concise reproductible code.
  • Asterite work-around was working
  • I assume it was related to general generic inheritance issue. Until Generic inheritance is fixed, there's no need to keep a duplicate here, no?
  • I was trying to do some clean-up of my issue yesterday. Eventually I cleaned too much maybe 馃槄

Anyway, the lack of concise reproductible code makes this issue difficult to check if yes or no this is working through spec or else. ~There's the branch on my shards but I'm not even sure it is still compatible with crystal 0.25.~ The issue remain on my branch tho.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

malte-v picture malte-v  路  77Comments

HCLarsen picture HCLarsen  路  162Comments

MakeNowJust picture MakeNowJust  路  64Comments

akzhan picture akzhan  路  67Comments

benoist picture benoist  路  59Comments