2014-11-22 23 views
4

我为具有非常有限的RAM值的系统编写应用程序。由于应用程序崩溃总是可能的,它使用动态内存分配,我创建的回调,所有可能的方式应用可以停止和清理所有的缓冲区那里,就像这样:强制内核在SIGSEGV挂钩时转储进程

sigaddset (&sigact.sa_mask, SIGSEGV); 
sigaction (SIGSEGV, &sigact, (struct sigaction*) NULL); 

它触发了一些通知的行动,并试图重新启动本身几次。 但我仍然想知道是什么导致了崩溃,所以我需要crashdump。 GDB不适合这么小的系统,只有内核级别的核心转储是可能的。但由于应用程序截获了这样一个信号,毕竟它自己退出,所以内核没有收到信号 - 没有核心创建。
我不能发出

kill(getpid(), kernel_signal); 

,因为它导致递归 - 这个信号也被截断。在这种情况下可以吗?

+2

的['abort'(http://man7.org/linux/man-pages/man3/abort.3.html)功能可以帮助,除非你赶上'SIGABRT'太(你不该“T)。 – 2014-11-22 12:31:03

+0

你尝试过'SIGQUIT'吗? [这个答案](http://stackoverflow.com/a/5648539/464709)提到它是强制核心转储的正确方法。或者,[unix.se]上的[这个回答](http://unix.stackexchange.com/a/11191)表明分叉进程并让孩子立即中止。它也可能适用于你的情况。 – 2014-11-22 12:31:16

+0

由于某种原因,SIGQUIT不会触发核心创建,但SIGABRT会这样做。 Joachim,请将您的评论作为答案 - 这是正确的。我测试了它,并且它做了我想要的所有 – pugnator 2014-11-22 12:58:57

回答

2

也许不是核心转储,你可以打印出一个回溯。这应该使用更少的内存并且是一个可捕获的信号。请看这个信号处理程序。

#include <execinfo.h> 

/* This signal handler ensures clean exits while not running in daemon mode */ 
void signal_handler(int type) 
{ 
    fprintf(stderr, "\nSIGNAL CAUGHT: %d: ", type); 

    switch (type) 
    { 
    case SIGSEGV: 
     { 
#ifdef GLIBC 
      { 
       void *array[10]; 
       size_t size; 

       // get void*'s for all entries on the stack 
       size = backtrace(array, 10); 

       // print out all the frames to stderr 
       fprintf(stderr, "Error: signal %d:\n", type); 
       backtrace_symbols_fd(array, size, STDERR_FILENO); 

       // DO CLEANUP HERE 
      } 
#else // Cause ulibc is terrible 
      fprintf(stderr, "SEGMENTATION FAULT"); 

      // DO CLEANUP HERE 

      break; 
     } 
#endif 
    case SIGINT: 
    case SIGTERM: 
    case SIGHUP: 
    default: 
     { 
      // DO CLEANUP HERE 
     } 

    } 
} 
+0

完美!真漂亮!我应该找出关于C的其他事情? :) – pugnator 2014-11-22 22:51:15

+2

只是想补充说,为了让函数名称通过回溯来识别,程序应该用-rdynamic选项(GCC)编译。默认情况下,它从动态链接表中获取名称。为了强制使用所有功能 - 我们需要该选项 – pugnator 2014-11-23 00:33:31