I went searching today to figure out why segfault handlers output method arguments, more than just method names, ex:
$ cat def go
Exception::CallStack.print_backtrace
pp caller
end
puts go
...
[0x55df0acdae16] *Exception::CallStack::print_backtrace:Nil +118 in ./me
[0x55df0acc9466] *go:Array(String) +6 in ./me
[0x55df0acb8cfe] __crystal_main +1230 in ./me
[0x55df0ad5cd96] *Crystal::main_user_code<Int32, Pointer(Pointer(UInt8))>:Nil +6 in ./me
[0x55df0ad5ccd9] *Crystal::main<Int32, Pointer(Pointer(UInt8))>:Int32 +41 in ./me
[0x55df0acc65e6] main +6 in ./me
[0x7f963e993b6b] __libc_start_main +235 in /lib/x86_64-linux-gnu/libc.so.6
[0x55df0acb876a] _start +42 in ./me
whereas normal exception stacktraces only list the method name
["me.cr:3:3 in 'go'",
"me.cr:5:1 in '__crystal_main'",
"src/crystal/main.cr:115:5 in 'main_user_code'",
"src/crystal/main.cr:101:7 in 'main'",
"src/crystal/main.cr:127:3 in 'main'",
"/lib/x86_64-linux-gnu/libc.so.6 in '__libc_start_main'",
"./me in '_start'",
"???"]
This eventually led me to the CRYSTAL_CALLSTACK_FULL_INFO environment variable, which changes it:
$ CRYSTAL_CALLSTACK_FULL_INFO=1 ./me
...
["me.cr:3:3 in '*go:Array(String)' at 0x562e5cac446b",
"me.cr:5:1 in '__crystal_main' at 0x562e5cab3cfe",
"src/crystal/main.cr:115:5 in '*Crystal::main_user_code<Int32, Pointer(Pointer(UInt8))>:Nil' at 0x562e5cb57d96",
"src/crystal/main.cr:101:7 in '*Crystal::main<Int32, Pointer(Pointer(UInt8))>:Int32' at 0x562e5cb57cd9",
"src/crystal/main.cr:127:3 in 'main' at 0x562e5cac15e6",
"/lib/x86_64-linux-gnu/libc.so.6 in '__libc_start_main' at 0x7fd869c61b6b",
"./me in '_start' at 0x562e5cab376a",
"??? at 0x0"]
which I agree is too much.
But it doesn’t seem right that by default we don’t get “rich” call stacks that include argument types, those could be useful at times. Anybody averse to if I do a PR to have the default include method with parameter types (but not ip addresses)? Thoughts?
Cheers!