在ptraced Linux进程中调用ptrace
有人在
Wikipedia “ptrace” article中声称,在Linux上,一个ptraced进程本身无法进行另一个进程.我试图确定是否(以及如果是这样的原因)就是这种情况.下面是一个我试图测试的简单程序.我的程序失败(子子进程无法正常运行)但我确信这是我的错误,而不是基本的东西.
从本质上讲,初始过程A分叉进程B进而分叉C.对其子B进行ptra,B对其子进行处理C.一旦它们被设置,所有三个进程都被写入只打印A,B或C到stdout每秒一次. 在实践中发生的事情是A和B工作正常,但C只打印一次然后卡住.检查ps -eo pid,cmd,wchan显示C卡在内核函数ptrace_stop中,而其余的都在hrtimer_nanosleep中,我希望这三个都是. 偶尔三个都可以工作(所以程序打印Cs以及As和Bs),这让我相信初始设置中存在一些竞争条件. 我猜测可能出现的问题是: >与A有关A看到与B相关的SIGCHLD看到SIGCHLD与C的信号有关,并等待(2)将??两者报告为来自B(但是对两个pids的一个hacky调用PTRACE_CONT并不能解决问题) ? 谁能弄清楚我做错了什么?谢谢. #include <stdio.h> #include <string.h> #include <unistd.h> #include <signal.h> #include <sys/ptrace.h> #include <sys/wait.h> static void a(){ while(1){ printf ("An"); fflush(stdout); sleep(1); } } static void b(){ while(1){ printf ("Bn"); fflush(stdout); sleep(1); } } static void c(){ while(1){ printf ("Cn"); fflush(stdout); sleep(1); } } static void sigchld_handler(int sig){ int result; pid_t child_pid = wait(NULL); // find who send us this SIGCHLD printf("SIGCHLD on %dn",child_pid); result=ptrace(PTRACE_CONT,child_pid,sig,NULL); if(result) { perror("continuing after SIGCHLD"); } } int main(int argc,char **argv){ pid_t mychild_pid; int result; printf("pidA = %dn",getpid()); signal(SIGCHLD,sigchld_handler); mychild_pid = fork(); if (mychild_pid) { printf("pidB = %dn",mychild_pid); result = ptrace(PTRACE_ATTACH,mychild_pid,NULL,NULL); if(result==-1){ perror("outer ptrace"); } a(); } else { mychild_pid = fork(); if (mychild_pid) { printf("pidC = %dn",mychild_pid); result = ptrace(PTRACE_ATTACH,NULL); if(result==-1){ perror("inner ptrace"); } b(); } else { c(); } } return 0; } 解决方法
你确实看到了竞争条件.你可以通过放睡来重复发生它(1);紧接在第二次fork()调用之前.
由于进程A未正确地将信号传递给进程B,因此导致竞争条件.这意味着如果进程B在进程A开始跟踪进程B之后开始跟踪进程C,则进程B永远不会获得指示进程C已停止的SIGCHLD信号,所以它永远不会继续下去. 要解决此问题,您只需修复SIGCHLD处理程序: static void sigchld_handler(int sig){ int result,status; pid_t child_pid = wait(&status); // find who send us this SIGCHLD printf("%d received SIGCHLD on %dn",getpid(),child_pid); if (WIFSTOPPED(status)) { result=ptrace(PTRACE_CONT,WSTOPSIG(status)); if(result) { perror("continuing after SIGCHLD"); } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |