如何将调试器附加到正在运行的 Perl 进程?
我有一个正在运行的 Perl 进程被卡住了,我想用调试器查看内部,看看出了什么问题。我无法重新启动该过程。我可以将调试器附加到正在运行的进程吗?我知道我可以执行gdb -p
,但是gdb
对我没有帮助。我尝试过 Enbugger,但失败了:
$ perl -e 'while (1) {}'&
[1] 86836
$ gdb -p 86836
…
Attaching to process 86836.
Reading symbols for shared libraries . done
Reading symbols for shared libraries ............................. done
Reading symbols for shared libraries + done
0x000000010c1694c6 in Perl_pp_stub ()
(gdb) call (void*)Perl_eval_pv("require Enbugger;Enbugger->stop;",0)
perl(86836) malloc: *** error for object 0x3: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
Program received signal SIGABRT, Aborted.
0x00007fff8269d82a in __kill ()
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (Perl_eval_pv) will be abandoned.
(gdb)
我做错了吗?还有其他选择吗?
PS 如果您认为自己可以从附加到正在运行的进程的调试器中受益,您可以插入由 SIGUSR1 触发的调试器后门:
use Enbugger::OnError 'USR1';
然后您可以简单地kill -USR1 pid
,您的进程将跳转到调试器。
I have a running Perl process that’s stuck, I’d like to poke inside with a debugger to see what’s wrong. I can’t restart the process. Can I attach the debugger to the running process? I know I can do gdb -p
, but gdb
does not help me. I’ve tried Enbugger, but failed:
$ perl -e 'while (1) {}'&
[1] 86836
$ gdb -p 86836
…
Attaching to process 86836.
Reading symbols for shared libraries . done
Reading symbols for shared libraries ............................. done
Reading symbols for shared libraries + done
0x000000010c1694c6 in Perl_pp_stub ()
(gdb) call (void*)Perl_eval_pv("require Enbugger;Enbugger->stop;",0)
perl(86836) malloc: *** error for object 0x3: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
Program received signal SIGABRT, Aborted.
0x00007fff8269d82a in __kill ()
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (Perl_eval_pv) will be abandoned.
(gdb)
Am I doing it wrong? Are there other options?
P.S. If you think you could benefit from a debugger attached to a running process yourself, you can insert a debugger back door triggered by SIGUSR1:
use Enbugger::OnError 'USR1';
Then you can simply kill -USR1 pid
and your process will jump into the debugger.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
首先,如果您想使用 gdb 检查它,请使用调试 perl。
请定义“卡住”。忙或非忙等待(CPU 高或低),是否吃内存?
while 1 则忙于等待。自 5.15 以来,我通常忙于等待(无休止的循环)Perl_hfree_next_entry() 中的 HV 损坏。非忙等待通常是等待阻塞 IO 读取。
我得到了正确的结果:
并且可以检查所有内容,比使用简单的 perl 调试器要多得多。使用非线程 Perl,您必须输入更少的内容。
等等。
如果您必须使用 perl:在 pp_stub 函数内部,进入 Enbugger 运行循环不是一个好主意,您应该位于 dump.c 的主运行循环中。在所示行设置断点。
eval 上的“对象 0x3 错误”听起来像是上下文中的内部损坏,因此您应该查看 cx 和堆栈指针。可能是因为你是在一个糟糕的环境中开始的。
First, please use a DEBUGGING perl, if you want to inspect it with gdb.
Please define "stuck". Busy or non-busy waiting (high or low CPU), eating memory or not?
With while 1 it is busy waiting. I usually get busy waiting (endless cycles) on HV corruption in Perl_hfree_next_entry() since 5.15. Non-busy waiting is usually waiting on a blocking IO read.
I get the correct:
and can inspect everything, much more than with a simple perl debugger. With a non-threaded perl you have to type less.
and so on.
If you have to do with perl: Inside the pp_stub function it is not a good idea to enter the Enbugger runloop, you should be in the main runloop in dump.c. Set a breakpoint to the shown line.
"error for object 0x3" on eval sound like internal corruption in the context, so you should look at the cx and stack pointers. Probably because you started it in a bad context.
我从未使用过 gdb,但也许你可以从 strace 中得到一些有用的东西?
I've never used gdb, but maybe you could get something useful out of strace?
http://metacpan.org/pod/App::Stacktrace
“perl-stacktrace 打印给定 Perl 进程的 Perl 线程的 Perl 堆栈跟踪。对于每个 Perl 框架,都会打印完整的文件名和行号。”
http://metacpan.org/pod/App::Stacktrace
“perl-stacktrace prints Perl stack traces of Perl threads for a given Perl process. For each Perl frame, the full file name and line number are printed.”
设置
.gdbinit
中:基本上,
perl_init
为 perl 调试器设置终端。如果 stdin/stdout/stderr 被调试进程重定向,则如果没有上述设置,则无法与 perl 调试器交互。如果需要,您可以从备份描述符 $old_stdin/$old_stdout/$old_stderr 恢复旧的重定向。附加到 perl 进程
通过 GDB 的 PID 附加到你的 perl 程序:
<前><代码>(gdb)attach_perl 640368
[启用使用libthread_db进行线程调试]
使用主机 libthread_db 库“/lib/x86_64-linux-gnu/libthread_db.so.1”。
__GI___select 中的 0x00007fd0b1313984 (nfds=0、readfds=0x0、writefds=0x0、 exceptfds=0x0、超时=0x7fff19c97240)位于 ../sysdeps/unix/sysv/linux/select.c:69
69 ../sysdeps/unix/sysv/linux/select.c:没有这样的文件或目录。
1 美元 = 7
2 美元 = 8
3 美元 = 9
4 美元 = 10
5 美元 = 11
6 美元 = 0
7 美元 = 1
8 美元 = 2
$9 = (无效*) 0x562cae6a7810
$10 = (无效 *) 0x562cad300ee0
从 perl5db.pl 版本 1.60 加载数据库例程
提供编辑器支持。
输入 h 或“h h”获取帮助,或输入“man perldebug”获取更多帮助。
$11 = (无效 *) 0x562cad6322d0
我的::SafeProcess::(lib/My/SafeProcess.pm:543):
第543章1000;
DB<1>
有时您不会在 p.3 中得到提示,因此您按 Ctrl+C 并运行
perl_stop
:只要加载了 Enbugger,您就可以随时通过
perl_stop
从 GDB 进入 perl 调试器。您需要知道的可能就是堆栈跟踪:
<前><代码> DB<1>;时间
@ = DB::DB 从文件 '(eval 39)[/usr/lib/x86_64-linux-gnu/perl-base/IO/Select.pm:130]' 第 1 行调用
$ = eval 'Enbugger->stop' 从文件 '/usr/lib/x86_64-linux-gnu/perl-base/IO/Select.pm' 第 130 行调用
@ = IO::Select::can_read(ref(IO::Select), 1) 从文件 '/home/midenok/src/mariadb/10.4/src/mysql-test/mysql-test-run.pl' 行调用第594章
@ = main::run_test_server(ref(IO::Socket::INET), ref(ARRAY), ref(HASH)) 从文件 '/home/midenok/src/mariadb/10.4/src/mysql-test/mysql 调用-test-run.pl' 第 485 行
。 = main::main() 从文件'/home/midenok/src/mariadb/10.4/src/mysql-test/mysql-test-run.pl'第343行调用
这里最新的执行点是 Select.pm 第 130 行,不要对注入的
eval 'Enbugger->stop'
感到惊讶,但有时您只会看到正常的堆栈跟踪。< /p>从 perl 进程分离
<前><代码> DB<1>; c
[从子进程 641324 分叉后分离]
[从子进程 641326 分叉后分离]
[fork 后与子进程分离 641328]
[fork 后与子进程分离 641329]
<前><代码>^C
程序收到信号SIGINT,中断。
__GI___select 中的 0x00007fd0b1313984 (nfds=0、readfds=0x0、writefds=0x0、 exceptfds=0x0、超时=0x7fff19c97240)位于 ../sysdeps/unix/sysv/linux/select.c:69
69 在 ../sysdeps/unix/sysv/linux/select.c
(gdb) 退出
与程序分离:/usr/bin/perl,进程 640368
[下级1(进程640368)分离]
Setup
.gdbinit
:Basically
perl_init
sets up terminal for perl debugger. If stdin/stdout/stderr was redirected by the debugged process you cannot interact perl debugger without the above setup. You can recover old redirections from the backup descriptors $old_stdin/$old_stdout/$old_stderr if needed.Attach to perl process
Attach to your perl program by PID from GDB:
Sometimes you will not get prompt in p.3, so you press Ctrl+C and run
perl_stop
:Any time you can get from GDB to perl debugger by
perl_stop
as long as Enbugger is loaded.All you need to know is probably the stack trace:
Here the latest execution point is Select.pm line 130, don't get surprised by injected
eval 'Enbugger->stop'
, but sometimes you will see just a normal stack trace.Detach from perl process