如何使用GDB调试带有信号处理的代码?
我正在调试下面的代码。一旦父进程接收到一个信号,调试器就会在介入时显示我在父处理程序代码中。但从那以后,我就无法控制GDB了。当我点击continue(继续)时,它会进入某个文件并停止,并显示以下消息:如何使用GDB调试带有信号处理的代码?,gdb,Gdb,我正在调试下面的代码。一旦父进程接收到一个信号,调试器就会在介入时显示我在父处理程序代码中。但从那以后,我就无法控制GDB了。当我点击continue(继续)时,它会进入某个文件并停止,并显示以下消息: Program received signal SIGTRAP, Trace/breakpoint trap. _dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:34 34 ../sysdeps/x86_64/dl-tram
Program received signal SIGTRAP, Trace/breakpoint trap.
_dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:34
34 ../sysdeps/x86_64/dl-trampoline.S: No such file or directory.
(gdb) continue
当我尝试继续时,它会重复出现新文件
显示跟随分叉模式和显示分叉分离的输出
(gdb) b 78
Breakpoint 1 at 0x400bba: file main.c, line 78.
(gdb) run
Starting program: /home/samkit/Posix_Programming/unix_Simple_prodcon_con_prob/main
Child sending signal
Breakpoint 1, main (argc=1, argv=0x7fffffffdf48) at main.c:79
79 if(cpid==0){
(gdb) show follow-fork-mode
Debugger response to a program call of fork or vfork is "parent".
(gdb) show detach-on-fork
Whether gdb will detach the child of a fork is on.
(gdb)
还尝试切换到GDB中的子进程,在第78行设置断点,然后运行。子进程向父进程发送信号并从父进程接收SIGUSR2。并因此进入它自己的处理程序。在这之后,GDB无法返回(与上面类似),下面是输出:
(gdb) set follow-fork-mode child
(gdb) set detach-on-fork on
(gdb) b 78
Breakpoint 1 at 0x400bba: file main.c, line 78.
(gdb) run
Starting program: /home/samkit/Posix_Programming/unix_Simple_prodcon_con_prob/main
[New process 31109]
[Switching to process 31109]
Breakpoint 1, main (argc=1, argv=0x7fffffffdf48) at main.c:79
79 if(cpid==0){
(gdb) next
83 if((child_sm_id = shmget(key,size*sizeof(char),0))==-1){ // Allocate shared memory
(gdb) next
87 if((child_sm_ptr = shmat(child_sm_id,NULL,0)) == (void *)-1){ // Attach shared memory to your address space
(gdb) next
95 printf("Child sending signal\n");
(gdb) next
Child sending signal
96 kill(getppid(),SIGUSR1);
(gdb) next
Received Signal 10
Sending signal
Program received signal SIGUSR2, User defined signal 2.
0x00007ffff7a4b267 in kill () at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) next
childHandler (sig=0) at main.c:25
25 void childHandler(int sig){
(gdb) next
26 printf("Child received Signal %d\n",sig);
(gdb) next
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000000004006e6 in printf@plt ()
(gdb) next
Single stepping until exit from function printf@plt,
which has no line number information.
0x00000000004006b0 in ?? ()
(gdb) next
Cannot find bounds of current function
(gdb)
我也尝试了继续,但我认为既然GDB看到了一个陷阱,如果我尝试继续,它就会一次又一次地重新执行这个陷阱
(gdb) continue
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000000004006b6 in ?? ()
(gdb) ccontinue
Undefined command: "ccontinue". Try "help".
(gdb) continue
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
_dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:34
34 ../sysdeps/x86_64/dl-trampoline.S: No such file or directory.
(gdb) continue
Continuing.
现在我的问题是:
Q1)如何使GDB实际继续执行?
问题2)我有2个进程。如果我在fork和do info线程之后放置一个断点,它将显示1个进程和1个线程。它不应该显示两个过程吗
代码:
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义BUFF_大小1024
结构smbuffer{
字符缓冲区[1024];
整数计数;
};
无效父处理程序(int-sig){
printf(“接收到的信号%d\n”,sig);
}
void childHandler(int-sig){
printf(“子接收信号%d\n”,sig);
}
int main(int argc,char*argv[]){
/*子相关属性*/
pid_t cpid;
智力状态;
内部检索;
/*共享内存初始化*/
int sm_id;
结构smbuffer*sm_ptr;
键=1100;
int size=BUFF_size;
如果((sm|u id=shmget(key,size*sizeof(char),0666 | IPC|u CREAT))=-1){//分配共享内存
perror(“SHMGET失败:\n”);
出口(1);
}
如果((sm_ptr=shmat(sm_id,NULL,0))==(void*)-1{//将共享内存附加到地址空间
perror(“SHMAT失败:\n”);
出口(1);
}
//初始化信号和处理器
结构sigaction-childold;
struct-sigaction-childnew;
childnew.sa_handler=childHandler;
sigset\u t儿童面具;
SIGEPTYSET(&childmask);
childnew.sa_mask=childmask;
childnew.sa_标志=0;
sigaction(SIGUSR2、childnew和childold);
//初始化信号和处理器
结构sigaction parentold;
结构sigaction parentnew;
parentnew.sa_handler=parentHandler;
sigset\u t父掩码;
sigeptypyset(和parentmask);
parentnew.sa_mask=parentmask;
parentnew.sa_标志=0;
sigaction(SIGUSR1、parentnew和parentold);
如果((cpid=fork())=-1){
perror(“Fork失败:\n”);
}
如果(cpid==0){
/*子代码*/
结构smbuffer*child\u smu ptr;
int child_sm_id;
如果((child_sm_id=shmget(key,size*sizeof(char),0))==1{//分配共享内存
perror(“子shmget失败:\n”);
出口(2);
}
如果((child_sm_ptr=shmat(child_sm_id,NULL,0))==(void*)-1){//将共享内存附加到地址空间
perror(“子shmat失败:\n”);
出口(2);
}
//向父循环发送信号并等待来自父循环的信号
而(1){
printf(“子发送信号”);
kill(getppid(),SIGUSR1);
sigsupspend(和childmask);
睡眠(1);
}
if(shmdt(child_sm_ptr)==-1){//deattach共享内存
perror(“子shmdt失败:\n”);
出口(2);
}
printf(“子出口”);
返回0;
}
否则{
/*父代码*/
//等待子信号和子信号。循环
而第(1)款{
sigsupspend(和parentmask);
printf(“发送信号”);
杀死(cpid,SIGUSR2);
睡眠(1);
}
}
if(shmdt(sm_ptr)==-1){//deattach共享内存
perror(“SHMDT失败:\n”);
出口(1);
}
//空闲共享内存
if((shmctl(sm_id,IPC_RMID,NULL))=-1){
perror(“Shmctl失败\n”);
出口(1);
}
printf(“代码结束\n”);
返回0;
}//主管道末端
你能把显示跟随fork模式
和在fork上显示分离
的输出包括在内吗?@MarkPlotnick我已经用outputsAnswer将帖子更新为Q2:当在fork上分离
打开时(默认),gdb将不控制子线程,信息线程
将只显示父线程。如果在目标分叉之前在gdb中执行set detach on fork off
,info threads
将显示这两个进程。我无法重现您在Q1中遇到的问题,但gdb会话中的main.c:79行实际上是您提供的代码中的第64行,所以可能还有一些我们没有看到的导致问题的额外代码。这可能是gdb中的错误handle SIGTRAP nostop
和handle SIGTRAP noprint
将让您更进一步,但这可能会影响gdb执行断点的能力。非常感谢@MarkPlotnick!!我至少可以继续执行noprint和nostop:)。非常感谢您的时间和精彩的回复。我学到了很多!
# include <signal.h>
# include <stdio.h>
# include <sys/types.h>
# include <sys/fcntl.h>
# include <sys/shm.h>
# include <sys/ipc.h>
# include <unistd.h>
# include <sys/wait.h>
#include <string.h>
#include <stdlib.h>
#define BUFF_SIZE 1024
struct smbuffer{
char buffer[1024];
int count;
};
void parentHandler(int sig){
printf("Received Signal %d\n",sig);
}
void childHandler(int sig){
printf("Child received Signal %d\n",sig);
}
int main( int argc, char* argv[] ) {
/* Child related attributes */
pid_t cpid;
int status;
int retval;
/* Shared memory initialization */
int sm_id;
struct smbuffer *sm_ptr;
key_t key = 1100;
int size = BUFF_SIZE;
if((sm_id = shmget(key , size * sizeof(char) , 0666|IPC_CREAT))== -1){ // Allocate shared memory
perror("SHMGET Failed : \n");
exit(1);
}
if((sm_ptr = shmat(sm_id,NULL,0))==(void *)-1){ // Attach shared memory to your address space
perror("SHMAT Failed : \n");
exit(1);
}
// Intilitialing Signals and handler
struct sigaction childold;
struct sigaction childnew;
childnew.sa_handler = childHandler;
sigset_t childmask ;
sigemptyset(&childmask);
childnew.sa_mask = childmask;
childnew.sa_flags = 0;
sigaction(SIGUSR2,&childnew,&childold);
// Intilitialing Signals and handler
struct sigaction parentold;
struct sigaction parentnew;
parentnew.sa_handler = parentHandler;
sigset_t parentmask ;
sigemptyset(&parentmask);
parentnew.sa_mask = parentmask;
parentnew.sa_flags = 0;
sigaction(SIGUSR1,&parentnew,&parentold);
if((cpid = fork())== -1){
perror("Fork Failed :\n");
}
if(cpid==0){
/* Child code */
struct smbuffer *child_sm_ptr;
int child_sm_id ;
if((child_sm_id = shmget(key,size*sizeof(char),0))==-1){ // Allocate shared memory
perror("Child shmget failed :\n");
exit(2);
}
if((child_sm_ptr = shmat(child_sm_id,NULL,0)) == (void *)-1){ // Attach shared memory to your address space
perror("Child shmat failed :\n");
exit(2);
}
// Signal parent and wait for signal from parent. Loop
while(1){
printf("Child sending signal\n");
kill(getppid(),SIGUSR1);
sigsuspend(&childmask);
sleep(1);
}
if(shmdt(child_sm_ptr)==-1){ // De-attach shared memory
perror("Child shmdt failed :\n");
exit(2);
}
printf("Child exit\n");
return 0;
}
else{
/* Parent code */
// Wait for child signal and signal child. Loop
while(1){
sigsuspend(&parentmask);
printf("Sending signal\n");
kill(cpid,SIGUSR2);
sleep(1);
}
}
if(shmdt(sm_ptr)==-1){ // De-attach shared memory
perror("SHMDT failed :\n");
exit(1);
}
// Free shared memory
if((shmctl(sm_id, IPC_RMID, NULL)) == -1){
perror("Shmctl failed \n");
exit(1);
}
printf("End of code\n");
return 0;
} // End of main