Changeset 4585

Show
Ignore:
Timestamp:
11/05/08 14:58:19 (2 months ago)
Author:
martin
Message:

separated backtrace functionality from leak_detective, used in

leak_detective
mutex profiling
signal handler

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/charon/daemon.c

    r4553 r4585  
    1717 */ 
    1818 
    19 #ifdef HAVE_DLADDR 
    20 # define _GNU_SOURCE 
    21 # include <dlfcn.h> 
    22 #endif /* HAVE_DLADDR */ 
    23  
    2419#include <stdio.h> 
    2520#include <sys/prctl.h> 
     
    3530#include <pwd.h> 
    3631#include <grp.h> 
    37 #ifdef HAVE_BACKTRACE 
    38 # include <execinfo.h> 
    39 #endif /* HAVE_BACKTRACE */ 
    4032#ifdef CAPABILITIES 
    4133#include <sys/capability.h> 
     
    4537 
    4638#include <library.h> 
     39#include <utils/backtrace.h> 
    4740#include <config/traffic_selector.h> 
    4841#include <config/proposal.h> 
     
    434427static void segv_handler(int signal) 
    435428{ 
    436 #ifdef HAVE_BACKTRACE 
    437     void *array[20]; 
    438     size_t size; 
    439     char **strings; 
    440     size_t i; 
    441  
    442     size = backtrace(array, 20); 
    443     strings = backtrace_symbols(array, size); 
    444  
    445     DBG1(DBG_JOB, "thread %u received %s. Dumping %d frames from stack:", 
    446          pthread_self(), signal == SIGSEGV ? "SIGSEGV" : "SIGILL", size); 
    447  
    448     for (i = 0; i < size; i++) 
    449     { 
    450 #ifdef HAVE_DLADDR 
    451         Dl_info info; 
    452          
    453         if (dladdr(array[i], &info)) 
    454         { 
    455             void *ptr = array[i]; 
    456             if (strstr(info.dli_fname, ".so")) 
    457             { 
    458                 ptr = (void*)(array[i] - info.dli_fbase); 
    459             } 
    460             DBG1(DBG_DMN, "    %s [%p]", info.dli_fname, ptr); 
    461         } 
    462         else 
    463         { 
    464 #endif /* HAVE_DLADDR */ 
    465             DBG1(DBG_DMN, "    %s", strings[i]); 
    466 #ifdef HAVE_DLADDR 
    467         } 
    468 #endif /* HAVE_DLADDR */ 
    469     } 
    470     free (strings); 
    471 #else /* !HAVE_BACKTRACE */ 
    472     DBG1(DBG_DMN, "thread %u received %s", 
    473          pthread_self(), signal == SIGSEGV ? "SIGSEGV" : "SIGILL"); 
    474 #endif /* HAVE_BACKTRACE */ 
     429    backtrace_t *backtrace; 
     430     
     431    DBG1(DBG_DMN, "thread %u received %d", pthread_self(), signal); 
     432    backtrace = backtrace_create(2); 
     433    backtrace->log(backtrace, stderr); 
     434    backtrace->destroy(backtrace); 
     435     
    475436    DBG1(DBG_DMN, "killing ourself, received critical signal"); 
    476437    raise(SIGKILL); 
     
    535496    sigaction(SIGSEGV, &action, NULL); 
    536497    sigaction(SIGILL, &action, NULL); 
     498    sigaction(SIGBUS, &action, NULL); 
    537499    action.sa_handler = SIG_IGN; 
    538500    sigaction(SIGPIPE, &action, NULL); 
  • trunk/src/libstrongswan/Makefile.am

    r4455 r4585  
    5151utils/optionsfrom.c utils/optionsfrom.h \ 
    5252utils/mutex.c utils/mutex.h \ 
     53utils/backtrace.c utils/backtrace.h \ 
    5354plugins/plugin_loader.c plugins/plugin_loader.h plugins/plugin.h 
    5455 
  • trunk/src/libstrongswan/utils/leak_detective.c

    r4311 r4585  
    1515 * $Id$ 
    1616 */ 
    17  
    18 #ifdef HAVE_DLADDR 
    19 # define _GNU_SOURCE 
    20 # include <dlfcn.h> 
    21 #endif /* HAVE_DLADDR */ 
    2217     
    2318#include <stddef.h> 
     
    2924#include <netinet/in.h> 
    3025#include <arpa/inet.h> 
    31 #include <dlfcn.h> 
    3226#include <unistd.h> 
    3327#include <syslog.h> 
     
    3630#include <printf.h> 
    3731#include <locale.h> 
    38 #ifdef HAVE_BACKTRACE 
    39 # include <execinfo.h> 
    40 #endif /* HAVE_BACKTRACE */ 
    4132 
    4233#include "leak_detective.h" 
     
    4435#include <library.h> 
    4536#include <debug.h> 
     37#include <utils/backtrace.h> 
    4638 
    4739typedef struct private_leak_detective_t private_leak_detective_t; 
     
    10799     
    108100    /** 
    109      * Stack frames at the time of allocation 
    110      */ 
    111     void *stack_frames[STACK_FRAMES_COUNT]; 
    112      
    113     /** 
    114      * Number of stacks frames obtained in stack_frames 
    115      */ 
    116     int stack_frame_count; 
    117      
    118     /** 
    119101     * Pointer to previous entry in linked list 
    120102     */ 
     
    125107     */ 
    126108    memory_header_t *next; 
     109     
     110    /** 
     111     * backtrace taken during (re-)allocation 
     112     */ 
     113    backtrace_t *backtrace; 
    127114     
    128115    /** 
     
    152139    magic: MEMORY_HEADER_MAGIC, 
    153140    bytes: 0, 
    154     stack_frame_count: 0
     141    backtrace: NULL
    155142    previous: NULL, 
    156143    next: NULL 
     
    161148 */ 
    162149static bool installed = FALSE; 
    163  
    164 /** 
    165  * log stack frames queried by backtrace() 
    166  * TODO: Dump symbols of static functions. This could be done with 
    167  * the addr2line utility or the GNU BFD Library... 
    168  */ 
    169 static void log_stack_frames(void **stack_frames, int stack_frame_count) 
    170 { 
    171 #ifdef HAVE_BACKTRACE 
    172     size_t i; 
    173     char **strings; 
    174      
    175     strings = backtrace_symbols(stack_frames, stack_frame_count); 
    176  
    177     fprintf(stderr, " dumping %d stack frame addresses:\n", stack_frame_count); 
    178     for (i = 0; i < stack_frame_count; i++) 
    179     { 
    180 #ifdef HAVE_DLADDR 
    181         Dl_info info; 
    182          
    183         if (dladdr(stack_frames[i], &info)) 
    184         { 
    185             char cmd[1024]; 
    186             FILE *output; 
    187             char c; 
    188             void *ptr = stack_frames[i]; 
    189              
    190             if (strstr(info.dli_fname, ".so")) 
    191             { 
    192                 ptr = (void*)(stack_frames[i] - info.dli_fbase); 
    193             } 
    194             snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", info.dli_fname, ptr); 
    195             if (info.dli_sname) 
    196             { 
    197                 fprintf(stderr, "  \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%x) [%p]\n", 
    198                         info.dli_fname, info.dli_fbase, info.dli_sname, 
    199                         stack_frames[i] - info.dli_saddr, stack_frames[i]); 
    200             } 
    201             else 
    202             { 
    203                 fprintf(stderr, "  \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname, 
    204                         info.dli_fbase, stack_frames[i]); 
    205             } 
    206             fprintf(stderr, "    -> \e[32m"); 
    207             output = popen(cmd, "r"); 
    208             if (output) 
    209             { 
    210                 while (TRUE) 
    211                 { 
    212                     c = getc(output); 
    213                     if (c == '\n' || c == EOF) 
    214                     { 
    215                         break; 
    216                     } 
    217                     fputc(c, stderr); 
    218                 } 
    219             } 
    220             else 
    221             { 
    222 #endif /* HAVE_DLADDR */ 
    223                 fprintf(stderr, "    %s\n", strings[i]); 
    224 #ifdef HAVE_DLADDR 
    225             } 
    226             fprintf(stderr, "\n\e[0m"); 
    227         } 
    228 #endif /* HAVE_DLADDR */ 
    229     } 
    230     free (strings); 
    231 #endif /* HAVE_BACKTRACE */ 
    232 } 
    233150 
    234151/** 
     
    239156 */ 
    240157char *whitelist[] = { 
     158    /* backtraces, including own */ 
     159    "backtrace_create", 
    241160    /* pthread stuff */ 
    242161    "pthread_create", 
     
    285204 * check if a stack frame contains functions listed above 
    286205 */ 
    287 static bool is_whitelisted(void **stack_frames, int stack_frame_count) 
    288 
    289     int i, j; 
    290      
    291 #ifdef HAVE_DLADDR 
    292     for (i=0; i< stack_frame_count; i++) 
    293     { 
    294         Dl_info info; 
    295          
    296         if (dladdr(stack_frames[i], &info) && info.dli_sname) 
    297         {    
    298             for (j = 0; j < sizeof(whitelist)/sizeof(char*); j++) 
    299             { 
    300                 if (streq(info.dli_sname, whitelist[j])) 
    301                 { 
    302                     return TRUE; 
    303                 } 
    304             } 
     206static bool is_whitelisted(backtrace_t *backtrace) 
     207
     208    int i; 
     209    for (i = 0; i < sizeof(whitelist)/sizeof(char*); i++) 
     210    { 
     211        if (backtrace->contains_function(backtrace, whitelist[i])) 
     212        { 
     213            return TRUE; 
    305214        } 
    306215    } 
    307 #endif /* HAVE_DLADDR */ 
    308216    return FALSE; 
    309217} 
     
    319227    for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) 
    320228    { 
    321         if (is_whitelisted(hdr->stack_frames, hdr->stack_frame_count)) 
     229        if (is_whitelisted(hdr->backtrace)) 
    322230        { 
    323231            whitelisted++; 
     
    327235            fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1); 
    328236            /* skip the first frame, contains leak detective logic */ 
    329             log_stack_frames(hdr->stack_frames + 1, hdr->stack_frame_count - 1); 
     237            hdr->backtrace->log(hdr->backtrace, stderr); 
    330238            leaks++; 
    331239        } 
     
    404312    hdr->magic = MEMORY_HEADER_MAGIC; 
    405313    hdr->bytes = bytes; 
    406     hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT); 
     314    hdr->backtrace = backtrace_create(3); 
    407315    tail->magic = MEMORY_TAIL_MAGIC; 
    408316    install_hooks(); 
     
    427335void free_hook(void *ptr, const void *caller) 
    428336{ 
    429     void *stack_frames[STACK_FRAMES_COUNT]; 
    430     int stack_frame_count; 
    431337    memory_header_t *hdr; 
    432338    memory_tail_t *tail; 
     339    backtrace_t *backtrace; 
    433340    pthread_t thread_id = pthread_self(); 
    434341    int oldpolicy; 
     
    456363                "header magic 0x%x, tail magic 0x%x:\n", 
    457364                ptr, hdr->magic, tail->magic); 
    458         stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); 
    459         log_stack_frames(stack_frames, stack_frame_count); 
     365        backtrace = backtrace_create(3); 
     366        backtrace->log(backtrace, stderr); 
     367        backtrace->destroy(backtrace); 
    460368    } 
    461369    else 
     
    467375        } 
    468376        hdr->previous->next = hdr->next; 
    469      
     377        hdr->backtrace->destroy(hdr->backtrace); 
     378         
    470379        /* clear MAGIC, set mem to something remarkable */ 
    471380        memset(hdr, MEMORY_FREE_PATTERN, hdr->bytes + sizeof(memory_header_t)); 
    472      
     381        
    473382        free(hdr); 
    474383    } 
     
    484393{ 
    485394    memory_header_t *hdr; 
    486     void *stack_frames[STACK_FRAMES_COUNT]; 
    487     int stack_frame_count; 
    488395    memory_tail_t *tail; 
     396    backtrace_t *backtrace; 
    489397    pthread_t thread_id = pthread_self(); 
    490398    int oldpolicy; 
     
    513421                "header magic 0x%x, tail magic 0x%x:\n", 
    514422                old, hdr->magic, tail->magic); 
    515         stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); 
    516         log_stack_frames(stack_frames, stack_frame_count); 
     423        backtrace = backtrace_create(3); 
     424        backtrace->log(backtrace, stderr); 
     425        backtrace->destroy(backtrace); 
    517426    } 
    518427    /* clear tail magic, allocate, set tail magic */ 
     
    524433    /* update statistics */ 
    525434    hdr->bytes = bytes; 
    526     hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT); 
     435    hdr->backtrace->destroy(hdr->backtrace); 
     436    hdr->backtrace = backtrace_create(3); 
    527437 
    528438    /* update header of linked list neighbours */ 
  • trunk/src/libstrongswan/utils/leak_detective.h

    r3589 r4585  
    2121#ifndef LEAK_DETECTIVE_H_ 
    2222#define LEAK_DETECTIVE_H_ 
    23  
    24 /** 
    25  * Maximum depth stack frames to register 
    26  */ 
    27 #define STACK_FRAMES_COUNT 20 
    2823 
    2924typedef struct leak_detective_t leak_detective_t; 
  • trunk/src/libstrongswan/utils/mutex.c

    r4575 r4585  
    2020#include <library.h> 
    2121#include <debug.h> 
     22#include <utils/backtrace.h> 
    2223 
    2324#include <pthread.h> 
     
    5455     
    5556    /** 
    56      * creator of the mutex 
    57      */ 
    58     void *stack[10]; 
    59      
    60     /** 
    61      * number of pointers in stack 
    62      */ 
    63     int stack_size; 
     57     * backtrace where mutex has been created 
     58     */ 
     59    backtrace_t *backtrace; 
    6460#endif /* LOCK_PROFILER */ 
    6561     
     
    112108 
    113109/** 
    114  * print mutex locking statistics 
    115  */ 
    116 static void print_stats(private_mutex_t *this) 
    117 
    118     int i; 
    119  
    120     DBG1("waited %d.%06ds in mutex, created at:", 
    121          this->waited.tv_sec, this->waited.tv_usec); 
    122     for (i = 0; i < this->stack_size; i++) 
    123     { 
    124         DBG1("  %p", this->stack[i]); 
    125     } 
    126 
    127  
    128 static void init_stats(private_mutex_t *this) 
    129 
    130     this->stack_size = backtrace(this->stack, countof(this->stack)); 
     110 * Print and cleanup mutex profiler 
     111 */ 
     112static void profiler_cleanup(private_mutex_t *this) 
     113
     114    fprintf(stderr, "waited %d.%06ds in mutex, created at:", 
     115            this->waited.tv_sec, this->waited.tv_usec); 
     116    this->backtrace->log(this->backtrace, stderr); 
     117    this->backtrace->destroy(this->backtrace); 
     118
     119 
     120/** 
     121 * Initialize mutex profiler 
     122 */ 
     123static void profiler_init(private_mutex_t *this) 
     124
     125    this->backtrace = backtrace_create(3); 
    131126    timerclear(&this->waited); 
    132127} 
     
    152147 
    153148/** dummy implementations */ 
    154 static void print_stats(private_mutex_t *this) {} 
    155 static void init_stats(private_mutex_t *this) {} 
     149static void profiler_cleanup(private_mutex_t *this) {} 
     150static void profiler_init(private_mutex_t *this) {} 
    156151 
    157152/** 
     
    225220static void mutex_destroy(private_mutex_t *this) 
    226221{ 
    227     print_stats(this); 
     222    profiler_cleanup(this); 
    228223    pthread_mutex_destroy(&this->mutex); 
    229224    free(this); 
     
    235230static void mutex_destroy_r(private_r_mutex_t *this) 
    236231{ 
    237     print_stats(&this->generic); 
     232    profiler_cleanup(&this->generic); 
    238233    pthread_mutex_destroy(&this->generic.mutex); 
    239234    pthread_key_delete(this->times); 
     
    259254            pthread_key_create(&this->times, NULL); 
    260255            this->generic.recursive = TRUE; 
    261             init_stats(&this->generic); 
     256            profiler_init(&this->generic); 
    262257            this->thread = 0; 
    263258             
     
    275270            pthread_mutex_init(&this->mutex, NULL); 
    276271            this->recursive = FALSE; 
    277             init_stats(this); 
     272            profiler_init(this); 
    278273             
    279274            return &this->public;