Mac环境下使用lldb调试依赖Rosetta2的Rails生产应用(解决double free崩溃及调试启动失败问题)
我完全懂你这种卡在调试环节的头疼——既要依赖Rosetta2跑Oracle相关的ruby-oci8 gem,又要解决malloc double free崩溃问题,还被lldb的架构适配卡着,太闹心了!不过你已经摸到关键点了,既然能在lldb里启动x86_64架构的Ruby,接下来只需要让这个Ruby进程加载Rails的启动脚本就行,咱们一步步来:
一、正确的lldb启动命令(核心解决思路)
你需要直接调用Ruby解释器,把Rails的启动脚本作为参数传进去——毕竟rails s本质上是ruby bin/rails s的快捷方式,lldb只能直接调试二进制程序(Ruby解释器),没法直接调试rails脚本。对应的命令如下:
lldb --arch x86_64 `asdf which ruby` -- bin/rails s -e production
这里的--是关键:它用来分隔lldb自身的参数和目标程序(Ruby)的参数,确保后面的bin/rails s -e production全部被传给Ruby进程,而不会被lldb当成自己的命令处理。
二、启动后的调试操作
当lldb加载完Ruby进程后,你可以先设置系统提示的调试断点,再启动进程追踪崩溃:
# 设置malloc错误断点,触发double free时会自动暂停 breakpoint set -n malloc_error_break # 启动Rails生产环境进程 process launch
当崩溃触发时,程序会停在断点处,你可以用lldb的常用命令排查问题:
bt:查看完整调用栈,定位崩溃的代码位置frame variable:查看当前栈帧的变量信息info threads:查看所有线程状态
三、关于attach失败的补充思路(可选)
之前尝试attach到Rosetta2进程失败,是因为苹果对转译进程的调试有SIP(系统完整性保护)限制。如果后续确实需要attach调试,可以尝试临时关闭SIP:
- 重启Mac,按住
Command + R进入恢复模式 - 打开终端,执行
csrutil disable - 重启Mac后再尝试attach操作
- 调试完成后,记得回到恢复模式执行
csrutil enable重新开启SIP(保障系统安全)
不过更推荐直接用前面的“从lldb启动进程”的方式,不用修改系统安全设置,更省心。
其实核心就是绕开直接启动rails脚本的误区,让lldb绑定到Ruby二进制上,同时指定x86_64架构适配Rosetta2,再把Rails的启动参数正确传递给Ruby解释器就搞定了!
备注:内容来源于stack exchange,提问作者Rohith

