17. Язык D
Переменная
Проба
Предикат
Действие
#!/usr/sbin/dtrace -s
BEGIN {
! c = 0;
! printf("How many times does ls call read?");
}
syscall::read:entry
/execname == "ls"/
{
c++;
}
END {
! printf("t%d times", c);
}
% ./test.d
dtrace: script './test.d' matched 3 probes
CPU ID FUNCTION:NAME
0 1 :BEGIN How many times does ls call
read?
^C
0 2 :END ! 6 times
Переменная
Проба
Предикат
Тело
Saturday, September 28, 13
18. Язык D
#!/usr/sbin/dtrace -s
BEGIN {
! c = 0;
! printf("How many times does ls call read?");
}
syscall::read:entry
/execname == "ls"/
{
c++;
}
END {
! printf("t%d times", c);
}
% ./test.d
dtrace: script './test.d' matched 3 probes
CPU ID FUNCTION:NAME
0 1 :BEGIN How many times does ls call
read?
^C
0 2 :END ! 6 times
Not thread safe!
Saturday, September 28, 13
22. • Не останавливаем приложение
• Не перекомпилируем
• Не запускаем его в дебагере
• Подключаемся на лету когда угодно и куда угодно
• Почти не теряем в производительности
Отладка: dtrace
Saturday, September 28, 13
23. Дебажим: кто сказал мяу?
Дано: некий демон zpool_worker активно дергает функции библиотеки libzfs.
Одна из библиотечных функций, zpool_vdev_attach(), по непонятной причине
возвращает ошибку.
Задача: Залезть в дебри libzfs и понять откуда именно и почему возвращается
ошибка
Saturday, September 28, 13
24. Дебажим: кто сказал мяу?
#!/usr/sbin/dtrace -s
pid$target::zpool_vdev_attach:entry
{
self->trace = 1;
}
pid$target:libzfs::return
/self->trace && (int)arg1 == -1/
{
ustack();
exit(0);
}
Провайдер pid, развернется в pid<ARG>
Saturday, September 28, 13
25. Дебажим: кто сказал мяу?
#!/usr/sbin/dtrace -s
pid$target::zpool_vdev_attach:entry
{
self->trace = 1;
}
pid$target:libzfs::return
/self->trace && (int)arg1 == -1/
{
ustack();
exit(0);
}
Модуль, нету модуля
Saturday, September 28, 13
26. Дебажим: кто сказал мяу?
#!/usr/sbin/dtrace -s
pid$target::zpool_vdev_attach:entry
{
self->trace = 1;
}
pid$target:libzfs::return
/self->trace && (int)arg1 == -1/
{
ustack();
exit(0);
}
Имя пробы
Saturday, September 28, 13
27. Дебажим: кто сказал мяу?
#!/usr/sbin/dtrace -s
pid$target::zpool_vdev_attach:entry
{
self->trace = 1;
}
pid$target:libzfs::return
/self->trace && (int)arg1 == -1/
{
ustack();
exit(0);
}
Thread local variable
Saturday, September 28, 13
29. Дебажим: кто сказал мяу?
#!/usr/sbin/dtrace -s
pid$target::zpool_vdev_attach:entry
{
self->trace = 1;
}
pid$target:libzfs::return
/self->trace && (int)arg1 == -1/
{
ustack();
exit(0);
}
Выполнить только если:
a) Мы пришли из zpool_vdev_attach()
b) Код возврата (arg1) == -1
Saturday, September 28, 13
30. Дебажим: кто сказал мяу?
#!/usr/sbin/dtrace -s
pid$target::zpool_vdev_attach:entry
{
self->trace = 1;
}
pid$target:libzfs::return
/self->trace && (int)arg1 == -1/
{
ustack();
exit(0);
}
Распечатать стэк и выйти
Saturday, September 28, 13
31. Дебажим: кто сказал мяу?
% ./who_said_meow.d -p 373
dtrace: script './who_said_meow.d' matched 478 probes
CPU ID FUNCTION:NAME
0 52733 zfs_ioctl:return
libzfs.so.1`zfs_ioctl+0x2c
zpool_worker`do_zpool_attach_or_replace+0x154
zpool_worker`zpool_rpc_attach+0x9f
zpool_worker`attach_invoke+0x70
zpool_worker`rpc_invoke+0xbb
zpool_worker`rpc_server_loop+0x9d
zpool_worker`rpc_worker_main_mode+0xc9
zpool_worker`rpc_worker_main+0x20
zpool_worker`main+0x6c
zpool_worker`_start+0x83
Saturday, September 28, 13
32. Дебажим: кто сказал мяу?
% dtrace -n 'fbt::zfs_ioc_vdev_attach:return /
execname=="zpool_worker"/ {trace(arg1);}'
dtrace: description 'fbt::zfs_ioc_vdev_attach:return ' matched 1
probe
CPU ID FUNCTION:NAME
0 60612 zfs_ioc_vdev_attach:return 16
Проделаем то же самое в пространстве ядра.
Для начала узнаем код ошибки...
Saturday, September 28, 13
33. Дебажим: кто сказал мяу?
% dtrace -n 'fbt::zfs_ioc_vdev_attach:return /
execname=="zpool_worker"/ {trace(arg1);}'
dtrace: description 'fbt::zfs_ioc_vdev_attach:return ' matched 1
probe
CPU ID FUNCTION:NAME
0 60612 zfs_ioc_vdev_attach:return 16
FBT: провайдер точек инструментирования ядерных функций
Saturday, September 28, 13
34. Дебажим: кто сказал мяу?
% dtrace -n 'fbt::zfs_ioc_vdev_attach:return /
execname=="zpool_worker"/ {trace(arg1);}'
dtrace: description 'fbt::zfs_ioc_vdev_attach:return ' matched 1
probe
CPU ID FUNCTION:NAME
0 60612 zfs_ioc_vdev_attach:return 16
Запускать пробу только если функцию дернул zpool_worker
Saturday, September 28, 13
35. Дебажим: кто сказал мяу?
#!/usr/sbin/dtrace -s
fbt::zfs_ioc_vdev_attach:entry
/execname == "zpool_worker"/
{
self->trace = 1;
}
fbt:zfs::return
/self->trace && arg1 == 16/
{
stack();
exit(0);
}
Saturday, September 28, 13
36. Дебажим: кто сказал мяу?
% ./who_said_meow_kern.d
dtrace: script './who_said_meow_kern.d' matched 2439 probes
CPU ID FUNCTION:NAME
0 61288 spa_open_ref:return
zfs`spa_open_common+0x279
zfs`spa_open+0x23
zfs`zfs_ioc_vdev_attach+0x32
zfs`zfsdev_ioctl+0x327
genunix`cdev_ioctl+0x45
specfs`spec_ioctl+0x5a
genunix`fop_ioctl+0x7b
genunix`ioctl+0x18e
unix`_sys_sysenter_post_swapgs+0x149
Saturday, September 28, 13
37. Flowindent: что делает redis?
#!/usr/sbin/dtrace -s
#pragma D option flowindent
pid$target:::entry
{
}
pid$target:::return
{
}
Saturday, September 28, 13
46. Кто стучится в порт ко мне?
#!/usr/sbin/dtrace -s
tcp:::receive
/args[4]->tcp_dport == 80/
{
@pkts[args[2]->ip_saddr] = count();
}
Saturday, September 28, 13
47. Кто стучится в порт ко мне?
#!/usr/sbin/dtrace -s
tcp:::receive
/args[4]->tcp_dport == 80/
{
@pkts[args[2]->ip_saddr] = count();
}
Saturday, September 28, 13
48. Кто стучится в порт ко мне?
#!/usr/sbin/dtrace -s
tcp:::receive
/args[4]->tcp_dport == 80/
{
@pkts[args[2]->ip_saddr] = count();
}
struct tcpinfo (TCP header fields)
Saturday, September 28, 13
49. Кто стучится в порт ко мне?
#!/usr/sbin/dtrace -s
tcp:::receive
/args[4]->tcp_dport == 80/
{
@pkts[args[2]->ip_saddr] = count();
}
struct ipinfo (IP information)
Saturday, September 28, 13
50. Кто стучится в порт ко мне?
#!/usr/sbin/dtrace -s
tcp:::receive
/args[4]->tcp_dport == 80/
{
@pkts[args[2]->ip_saddr] = count();
}
Императивная запись:
@pkts[<ip_daddr>]++
Saturday, September 28, 13
51. Кто стучится в порт ко мне?
#!/usr/sbin/dtrace -s
tcp:::receive
/args[4]->tcp_dport == 80/
{
@pkts[args[2]->ip_daddr] = count();
}
% ./port.d
...
192.168.0.50 34
192.168.0.102 11
192.168.0.12 2
Saturday, September 28, 13
52. Trace disk I/O size
#!/usr/sbin/dtrace -s
io:::start
{
printf("%d %s %d", pid, execname, args[0]->b_bcount);
}
Saturday, September 28, 13
71. Есть ли жизнь вне C?
• С++: name mangling
• Java: USDT
• node.js, perl, ruby: libusdt based providers
• libusdt: github.com/chrisa/libusdt/
Saturday, September 28, 13