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.
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
--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)
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:
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.