定时器/信号调试始终在<timer_settime + 16>中结束

时间:2017-09-08 13:23:30

标签: c timer gdb signals

我正在使用gdb来调试启动计时器的代码。当定时器在gdb中振铃时,我总是在指令timer_settime + 16处结束。 这是预期的行为吗?

作为一个例子,我稍微修改了timer_settime手册页的代码。想法是传递两个参数:一个整数字符串和一个nsec值。代码启动计时器在nsec后响铃,然后复制字符串。 我期望通过递增nsec值,gdb停在不同的代码行,最终在复制循环内。但总是停在。

这是预期的行为吗?

是否记录在某处?

有没有办法达到我的预期(即:启动一个定时器,当振铃使gdb停止在程序刚刚(或之后)信号之前)? (始终具有nsec粒度)。

代码:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>

#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                           } while (0)

unsigned char OUT[32];
unsigned char IN[32];

unsigned char ascii2hex(char in){ 

unsigned char out;

    if( ('0' <= in) && (in <= '9') )
        out = in - '0';
    if( ('A' <= in) && (in <= 'F') )
        out = in - 'A' + 10;
    if( ('a' <= in) && (in <= 'f') )
        out = in - 'a' + 10;

    return out;
}

void asciiStr2hex(char * in, unsigned char * out, unsigned int len){

int i = 0;
int j = 0;
for( i = 0; i < len; i+=2){
        out[j++]  = (ascii2hex(in[i  ]) << 4) +  ascii2hex(in[i+1]);
    }
}

void testcode(unsigned char *out, unsigned char *in, unsigned int len){
unsigned int i;
for (i=0;i<len;i++)
    out[i] = in[i];
}

static void print_siginfo(siginfo_t *si)
{
   timer_t *tidp;
   int or;

   tidp = si->si_value.sival_ptr;

   printf("    sival_ptr = %p; ", si->si_value.sival_ptr);
   printf("    *sival_ptr = 0x%lx\n", (long) *tidp);

   or = timer_getoverrun(*tidp);
   if (or == -1)
       errExit("timer_getoverrun");
   else
       printf("    overrun count = %d\n", or);
   }

static void handler(int sig, siginfo_t *si, void *uc)
{
   /* Note: calling printf() from a signal handler is not
      strictly correct, since printf() is not async-signal-safe;
      see signal(7) */

   printf("Caught signal %d\n", sig);
   print_siginfo(si);
   signal(sig, SIG_IGN);
}

int main(int argc, char *argv[])
{
   timer_t timerid;
   struct sigevent sev;
   struct itimerspec its;
   long long freq_nanosecs;
   //sigset_t mask;
   struct sigaction sa;

   if (argc != 3) {
       fprintf(stderr, "Usage: %s <16byte> <time-nanosecs>\n",
               argv[0]);
       exit(EXIT_FAILURE);
   }

   asciiStr2hex(argv[1], IN, 32);

   /* Establish handler for timer signal */

   printf("Establishing handler for signal %d\n", SIG);
   sa.sa_flags = SA_SIGINFO;
   sa.sa_sigaction = handler;
   sigemptyset(&sa.sa_mask);
   if (sigaction(SIG, &sa, NULL) == -1)
       errExit("sigaction");

   /* Block timer signal temporarily */

/*     printf("Blocking signal %d\n", SIG);
       sigemptyset(&mask);
       sigaddset(&mask, SIG);
       if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1)
           errExit("sigprocmask");
*/
       /* Create the timer */

   sev.sigev_notify = SIGEV_SIGNAL;
   sev.sigev_signo = SIG;
   sev.sigev_value.sival_ptr = &timerid;
   if (timer_create(CLOCKID, &sev, &timerid) == -1)
       errExit("timer_create");

   printf("timer ID is 0x%lx\n", (long) timerid);

   /* Start the timer */

   freq_nanosecs = atoll(argv[2]);
   its.it_value.tv_sec = freq_nanosecs / 1000000000;
   its.it_value.tv_nsec = freq_nanosecs % 1000000000;
   its.it_interval.tv_sec = its.it_value.tv_sec;
   its.it_interval.tv_nsec = its.it_value.tv_nsec;

   if (timer_settime(timerid, 0, &its, NULL) == -1)
        errExit("timer_settime");

   /* Sleep for a while; meanwhile, the timer may expire
      multiple times */

   printf("Sleeping for %d seconds\n", atoi(argv[1]));

   testcode(OUT, IN, 16);


   /* Unlock the timer signal, so that timer notification
      can be delivered */

  /*   printf("Unblocking signal %d\n", SIG);
       if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
           errExit("sigprocmask");
  */
   exit(EXIT_SUCCESS);
}

使用r 00112233445566778899001122334455调试到gdb时2 我得到了:

Program received signal SIGUSR1, User defined signal 1.
0x76fc7c38 in timer_settime () from /lib/arm-linux-gnueabihf/librt.so.1
(gdb) x/30i $pc
=> 0x76fc7c38 <timer_settime+16>:   cmn r0, #4096   ; 0x1000
0x76fc7c3c <timer_settime+20>:  mov r4, r0
0x76fc7c40 <timer_settime+24>:  bhi 0x76fc7c4c <timer_settime+36>
0x76fc7c44 <timer_settime+28>:  mov r0, r4
0x76fc7c48 <timer_settime+32>:  pop {r3, r4, r7, pc}
0x76fc7c4c <timer_settime+36>:  bl  0x76fc55b4
0x76fc7c50 <timer_settime+40>:  rsb r3, r4, #0
0x76fc7c54 <timer_settime+44>:  mvn r4, #0
0x76fc7c58 <timer_settime+48>:  str r3, [r0]
0x76fc7c5c <timer_settime+52>:  b   0x76fc7c44 <timer_settime+28>
0x76fc7c60 <timer_settime+56>:  andeq   r0, r0, r2, lsl #2
0x76fc7c64: push    {r4, r5, r6, r7, r8, r9, r10, lr}
0x76fc7c68: sub sp, sp, #600    ; 0x258
0x76fc7c6c: ldr r4, [pc, #340]  ; 0x76fc7dc8
0x76fc7c70: add r1, sp, #512    ; 0x200
0x76fc7c74: add r4, pc, r4
0x76fc7c78: mov r0, r4
0x76fc7c7c: bl  0x76fc56b0
0x76fc7c80: cmp r0, #0
0x76fc7c84: bne 0x76fc7c98
0x76fc7c88: ldr r2, [sp, #512]  ; 0x200
0x76fc7c8c: ldr r3, [pc, #312]  ; 0x76fc7dcc
0x76fc7c90: cmp r2, r3
0x76fc7c94: beq 0x76fc7d94
0x76fc7c98: ldr r5, [pc, #304]  ; 0x76fc7dd0
0x76fc7c9c: ldr r0, [pc, #304]  ; 0x76fc7dd4
0x76fc7ca0: add r5, pc, r5
0x76fc7ca4: add r0, pc, r0
0x76fc7ca8: mov r1, r5
0x76fc7cac: bl  0x76fc5524

我在覆盆子pi上运行这样的代码,但我很确定我在另一台Linux机器x86_64上有相同的行为。 我已经测试了&#34;处理停止SIGUSR1&#34;。

1 个答案:

答案 0 :(得分:0)

我终于发现问题是我必须在gdb中set unwindonsignal off才能获得我期望的行为。