2010-10-22 19 views
4

Comme dansComment faire gdb get stacktrace de façon répétée?

for((;;)) { 
    gdb -batch -n -ex 'set pagination off' -ex 'thread apply all bt' ffplay_g `pidof ffplay_g` >> /tmp/qq; 
} 

, mais plus rapide, sans rupture de charge GDB et les symboles à chaque fois?

Les contre-mesures doivent être prises par le temporisateur, et non par le déclenchement de certains points d'arrêt.

+0

J'ai frappé ce comportement aussi, et non deviner. * Cependant *, j'ai oublié de mentionner ** lsstack ** est censé être un moyen indolore pour obtenir des échantillons utiles de la pile. –

Répondre

1

Comme recommandé par le commentaire If you want to stick with gdb, then why not script a gdb session? Your controller process can sleep for 50 ms, then wake up, send a ^C, t a a bt, c, and then go back to sleep. – Jeremy W. Sherman

http://vi-server.org/vi/bin/gdbdriver.pl

#!/usr/bin/perl -w 

use strict; 
use IPC::Open2; 

my $init = "run"; 
my $command = "bt"; 
my $delay = 1; 

my $need_int=0; 

$init = shift @ARGV; 
$delay = shift @ARGV; 
$command = shift @ARGV; 

die("Usage: gdbpriver.pl '' 0.1 'bt' gdb -q /path/to/proc 33344\n\tgdbdriver.pl init_command period_seconds backtrace_command startup_arguments\n") unless $ARGV[0]; 

my $pid = open2(\*OUT, \*IN, @ARGV); 

print "pid=$pid\n"; 

print IN "set pagination off\n"; 
print IN "$init\n"; 

while(<OUT>) { 
    if (/Starting program:/) { 
    $need_int=1; 
    last; 
    } 
    last if /\(gdb\)/; 
} 

sub intr() { 
    kill 9, $pid; 
    exit(0); 
} 
$SIG{'INT'} = \&intr; 
sub spipe() { 
    print "PIPE!\n"; 
} 
$SIG{'PIPE'} = \&spipe; 

if($need_int) { 
    kill 2, $pid; 
} 

for(;;) { 
    print IN "$command\n"; # backtrace 
    print IN "c\n"; # continue the program 
    while(<OUT>) { 
    last if /Continuing./; 
    print; 
    } 
    select undef, undef, undef, $delay; # sorry, nanosleep fails 
    print "INT\n"; 
    kill 2, $pid; # SIGINT to gdb to make it interrupt the program 
} 
0

Fixer, définissez le point d'arrêt, réglez les commandes sur ce point d'arrêt qui comprennent continue, puis continuer:

$ gdb attach ffplay_g 
. . . 
(gdb) b symbol 
(gdb) comm 1 
> t a a bt 
> c 
> end 
(gdb) c 

Si vous demandez comment avoir pause gdb régulièrement, eh bien, vous pouvez simplement boucle appeler étape puis backtrace, mais tu ne vas pas aller très loin très vite:

(gdb) while 1 
(gdb) t a a bt 
(gdb) s 
(gdb) end 

Si vous essayez de profil de votre processus, c'est la mauvaise façon. Regardez dans gprof ou (sous Mac OS/iOS) Shark.

+0

Non, pas gprof. Je veux qu'il soit déclenché par _time_ pas par _breakpoint dans le code_. Je ne veux pas "(gdb) s", mais plutôt "sleep 50 ms". –

+0

Il devrait se comporter comme le code en question. Ou comme {appuyer sur^C et taper "t a a bt" et "c"} de façon répétée. –

+0

Je pense que gprof n'est pas un bon paradigme, pour une foule de raisons: http://stackoverflow.com/questions/1777556/alternatives-to-gprof/1779343#1779343 –

2

sommeil système d'utilisation, cette commande gdb devrait faire l'affaire:

shell sleep 1