Как исправить ошибку при включенном зонде: неверный адрес (0x0)?

У меня следующая ошибка:

dtrace: error on enabled probe ID 3 (ID 7343: php15810:php:dtrace_execute_ex:function-return): invalid address (0x0) in action #2 at DIF offset 24

когда я пытаюсь отследить свой PHP-скрипт (sudo ./trace-php.d).

В основном, чего я хотел добиться, так это отображать время/количество распределения с помощью функции PHP. Вроде работает, но меня раздражает эта ошибка. Я знаю, что могу отправить это /dev/null, но я хотел бы понять и исправить это.

Вот мой код dtrace:

#!/usr/sbin/dtrace -Zs
#pragma D option quiet
php*:::function-entry
{
    self->vts = timestamp;
    self->cmd = arg0
}

php*:::function-return
/self->vts/
{
    @time[copyinstr(self->cmd)] = quantize(timestamp - self->vts);
    @num = count();
    self->vts = 0;
    self->cmd = 0;
}

profile:::tick-2s
{
  printf("\nPHP commands/second total: ");
  printa("%@d; commands latency (ns) by pid & cmd:", @num);
  printa(@time);
  clear(@time);
  clear(@num);
}

Пример вывода (при запуске некоторого php-скрипта):

dtrace: error on enabled probe ID 3 (ID 7343: php15810:php:dtrace_execute_ex:function-return): invalid address (0x0) in action #2 at DIF offset 24
dtrace: error on enabled probe ID 3 (ID 7343: php15810:php:dtrace_execute_ex:function-return): invalid address (0x0) in action #2 at DIF offset 24
dtrace: error on enabled probe ID 3 (ID 7343: php15810:php:dtrace_execute_ex:function-return): invalid address (0x0) in action #2 at DIF offset 24
dtrace: error on enabled probe ID 3 (ID 7343: php15810:php:dtrace_execute_ex:function-return): invalid address (0x0) in action #2 at DIF offset 24

PHP commands/second total: 1549; commands latency (ns) by pid & cmd:
  variable_get                                      
           value  ------------- Distribution ------------- count    
            1024 |                                         0        
            2048 |@@@@@@@@@@@@@@@@@@@@@@@@@@@              4        
            4096 |@@@@@@@                                  1        
            8192 |@@@@@@@                                  1        
           16384 |                                         0        

  __construct                                       
           value  ------------- Distribution ------------- count    
            1024 |                                         0        
            2048 |@@@@@@@@@@@@@@@@@@@@                     3        
            4096 |@@@@@@@@@@@@@                            2        
            8192 |@@@@@@@                                  1        
           16384 |                                         0        

  features_array_diff_assoc_recursive               
           value  ------------- Distribution ------------- count    
           16384 |                                         0        
           32768 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1        
           65536 |                                         0        

  features_export_info                              
           value  ------------- Distribution ------------- count    
            2048 |                                         0        
            4096 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@        122      
            8192 |@@@@@@                                   23       
           16384 |@                                        4        
           32768 |                                         0    

person kenorb    schedule 08.04.2016    source источник
comment
arg0 когда-нибудь NULL?   -  person Andrew Henle    schedule 11.04.2016
comment
Это имя_функции, поэтому я не уверен.   -  person kenorb    schedule 11.04.2016
comment
Кажется, не должно быть NULL... Возможно ли, что к тому времени, когда вы сделаете вызов copyinstr(), он станет недействительным?   -  person Andrew Henle    schedule 11.04.2016
comment
Не уверен, что каждый возврат функции должен предшествовать self-›cmd. Как узнать, в какой строке/месте это происходит? Действие № 2 при смещении DIF 24, я думаю, бессмысленно.   -  person kenorb    schedule 11.04.2016
comment
Вы используете только указатель в вызове copyinstr(). Это может иметь значение, хотя в данном случае адреса не были 0x0: stackoverflow.com/questions/1198114/ Вы можете попробовать переместить copyinstr() в зонд function-entry или добавить / arg0 / к зонду function-entry. Я подозреваю, что вы можете видеть, как PHP загружается сам и выполняет вызовы PHP до того, как он заполнит какую-то таблицу символов. Добавьте дополнительный зонд function-entry с / arg0 == 0 /, который выдает или сохраняет результаты от ustack().   -  person Andrew Henle    schedule 12.04.2016


Ответы (1)


Это, вероятно, сделает то, что вы хотите, разбив зонд php*:::function-return на разные предложения — одно для того, хотите ли вы печатать вывод или нет (в зависимости от того, является ли аргумент или не определен), а второй — для очистки локальных переменных вашего потока независимо от того, что вы сделали или не сделали в первом предложении probe.

При этом используется тот факт, что DTrace выполняет код для каждого зонда именно в том порядке, в котором вы определяете предложения.

В этом примере также используется уникальная комбинация клавиш probefunc и идентификатора потока (tid) для ваших собственных переменных, чтобы вы случайно не перезаписали эти локальные переменные потока при спуске. в вызовы функций:

#!/usr/sbin/dtrace -Zs

#pragma D option quiet

php*:::function-entry
{
    self->vts[tid,probefunc] = timestamp;
    self->cmd[tid,probefunc] = arg0
}

php*:::function-return
/self->vts[tid,probefunc] && self->cmd[tid,probefunc]/
{
    @time[copyinstr(self->cmd[tid,probefunc])] =
      quantize(timestamp - self->vts[tid,probefunc]);
    @num = count();
}

php*:::function-return
/self->vts[tid,probefunc]/
{
    self->vts[tid,probefunc] = 0;
    self->cmd[tid,probefunc] = 0;
}

profile:::tick-2s
{
  printf("\nPHP commands/second total: ");
  printa("%@d; commands latency (ns) by pid & cmd:", @num);
  printa(@time);
  clear(@time);
  clear(@num);
}

Вышеупомянутое может не сработать, если какая-либо из функций PHP была оптимизирована для хвостового вызова. Чтобы узнать, подвержены ли вы этому условию, выполните следующее:

#!/usr/sbin/dtrace -s

#pragma D option quiet

php*:::function-entry
{
  @e[probefunc,probename] = count();
}

php*:::function-return
{
  @r[probefunc,probename] = count();
}

tick-10sec
{
  printf("ENTRY POINTS\n");
  printa(@e);

  printf("RETURN POINTS\n");
  printa(@r);

  exit(0);
}

Отсортируйте точки входа и возврата — счетчики не обязательно должны точно совпадать, но вы хотите, чтобы каждая отдельная функция проверки и комбинация имен имели совпадение между точками входа и возврата. Будьте особенно осторожны с теми, для которых не указана точка возврата. Скорее всего, они оптимизированы для хвостового вызова, и вы захотите исключить их из своего анализа, так как вы никогда не сможете их рассчитать.

person Gordon Marler    schedule 28.04.2016
comment
Это здорово, спасибо. Я хотел бы проверить это, но он не печатает никаких данных (при запуске некоторого php), кроме сообщения. Ожидается, что это будет так? - person kenorb; 28.04.2016
comment
Возможно нет. Попробуйте запустить его без тихой опции и посмотрите, сколько зондов активируется на самом деле. Я не запускаю PHP (в основном C/C++/Fortran/Perl) с DTrace, поэтому, возможно, у этого провайдера есть некоторые особенности, к которым я не привык. - person Gordon Marler; 28.04.2016