Отладка странной ошибки, которая зависит от выбранного планировщика

0

Я испытываю странное поведение в программном обеспечении, над которым я работаю. Это контроллер в режиме реального времени, написанный на С++, работающий на Linux, и он широко использует многопоточность.

Когда я запускаю программу, не спрашивая ее в реальном времени, все работает так, как я ожидаю. Но когда я прошу переключиться в режим реального времени, есть отчетливо воспроизводимая ошибка, которая позволяет сбой приложения. Я думаю, это должно быть какая-то тупиковая вещь, потому что это мьютекс, который набирает тайм-аут и в конечном итоге вызывает утверждение.

Мой вопрос: как его отыскать. Глядя на обратную линию от произведенного ядра, не очень полезно, поскольку причина проблемы лежит где-то в прошлом.

В следующем коде происходит переключение между режимами "normal" и "realtime":

В main.cpp(упрощенный код возврата проверяется через утверждения):

if(startAsRealtime){
struct sched_param sp;
memset(&sp, 0, sizeof(sched_param));
sp.sched_priority = 99;
sched_setscheduler(getpid(), SCHED_RR, &sp);}

В каждом потоке (упрощенный код возврата проверяется посредством утверждений):

if(startAsRealtime){
sched_param param;
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_getschedparam(&attr, &param);
param.sched_priority = priority;
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);}

Заранее спасибо

Теги:
debugging
real-time

2 ответа

1

Если вы используете glibc как свою библиотеку C, вы можете использовать ответ на вопрос Возможно ли перечислить мьютексы, которые содержат нить, чтобы найти из потока, который удерживает мьютекс, который отключается. Это должно начать сужать вещи - вы можете проверить этот поток и выяснить, почему он не отказывается от мьютекса.

  • 0
    Я на самом деле знаю, какая нить содержит этот мьютекс. Проблема в том, что он не должен держать его запертым. Я просто не понимаю, почему при запуске всех потоков с одинаковым приоритетом ошибка не отображается, а при работе с RR-планировщиком с разными приоритетами.
  • 1
    @ user761451: Звучит так, как будто это может быть случай голодания или живой блокировки, а не подлинной тупиковой блокировки - если поток, содержащий мьютекс, имеет более высокий приоритет, он может разблокировать его, но всегда блокировать снова, пока поток с более низким приоритетом не получит шанс заблокировать это.
Показать ещё 1 комментарий
0

Один из ваших потоков в реальном времени может вращаться в цикле (не уступая), таким образом, голодающие другие потоки и приводящие к таймауту мьютекса.

Также может быть состояние гонки, которое проявляется только при переключении в режим реального времени. Время событий в режиме реального времени вызывает тупик.

Если у вас есть места, где вы приобретаете несколько уровней блокировок или блокируете рекурсивно, это должны быть первые места, которые вы подозреваете.

Если вы действительно не знаете, где проблема, попробуйте использовать метод двоичного поиска для брекетинга проблемы. Рекурсивно вырезать половину функциональности, пока вы не уменьшите ее до фактической проблемы. Возможно, вам придется издеваться над некоторыми подсистемами, которые временно вырезаны.

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

  • 0
    Это не голодание, загрузка процессора падает до нуля при возникновении ошибки, больше похоже на тупик. С другой стороны, тупик кажется маловероятным, так как программа содержит механизм обнаружения взаимоблокировок. Все потоки являются rt, потому что программа является частью контроллера большей системы, а не rt работает как отдельная программа. Я действительно знаю относительно точно, где проблема, я могу закомментировать некоторые вещи, и это уходит. Но я до сих пор не вижу, что на самом деле происходит. Я предполагаю, что есть основной недостаток дизайна, и я очень хочу его найти.
  • 0
    Отредактированный ответ для решения вопросов RT.
Показать ещё 7 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню