views:

20

answers:

2

Like in

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

, but faster, without reloading GDB and symbols every time?

Backtraces need to be taken by timer, not by triggering some breakpoints.

A: 

Attach, set the breakpoint, set commands on that breakpoint that include continue, and then continue:

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

If you are asking how to have gdb break in regularly, well, you could just loop calling step and then backtrace, but you're not going to get very far very fast:

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

If you're trying to profile your process, this is the wrong way. Look into gprof or (under Mac OS/iOS) Shark.

Jeremy W. Sherman
No, not gprof. I want it to be triggered by _time_ not by _breakpoint in the code_. I want not "(gdb) s", but more like "sleep 50 ms".
Vi
It should behave like code in question. Or like { pressing ^C and typing "t a a bt" and "c"} repeatably.
Vi
I think gprof is not a good paradigm, for a whole host of reasons: http://stackoverflow.com/questions/1777556/alternatives-to-gprof/1779343#1779343
Mike Dunlavey
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
@Mike I would recommend Shark over gprof any day. Shark does give instruction-level feedback on hotspots. Dtrace and Instruments can also help sometimes. But I don't know of a Linux equivalent for either.
Jeremy W. Sherman
Shark is better, but has a way to go. The best I've seen is Zoom on linux. For real work, I still rely on the manual method, because the insight from studying representative program states tells more than numbers any day. I'm not alone in thinking this way.
Mike Dunlavey
A: 

As recommended by the comment 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
}
Vi