Summary: | Похоже сломана работа таймеров с созданием потока в качестве уведомления. | ||||||
---|---|---|---|---|---|---|---|
Product: | Branch 5.0 | Reporter: | Roman Savochenko <rom_as> | ||||
Component: | glibc | Assignee: | Dmitry V. Levin <ldv> | ||||
Status: | RESOLVED LATER | QA Contact: | qa-5.0 <qa-5.0> | ||||
Severity: | critical | ||||||
Priority: | P4 | CC: | evg | ||||
Version: | unspecified | ||||||
Hardware: | all | ||||||
OS: | Linux | ||||||
Attachments: |
|
Description
Roman Savochenko
2009-03-25 19:00:46 MSK
Похоже в glibc проблемы с разделением доступа к общим данным таймеров и/или потоков. Остановил высоконагруженные потоки с периодичностью 5мс и общей нагрузкой процессора 40%(2ГГц) и таймера нормально поудалялись! Т.е причина не удаление в другом потоке, а проблема совместных ресурсов в GlibC. Кроме того на Branch4.1 x86_64 с kernel-2.6.18ovz у которого нет поддержки времени высокого разрешения и разрешение таймера 4мс, все таймера корректно удалились. Повышаю приоритет ошибки. На kernel-2.6.25 и glibc-2.5.1 из Branch 4.0 эта проблема ещё не проявляется. Тестил на ноуте в той-же конфигурации и полной загрузкой CPU тем-же источником. Ядро уже держит высокое разрешение времени. С компилятором, которым собирается программа, проблема не связана. Собрал gcc-4.3, gcc-4.1 и gcc-3.4, результат идентичен: (gdb) bt #0 0xb7ba64c0 in __gxx_personality_v0 () from /lib/librt.so.1 #1 0xb7bafdaa in start_thread () from /lib/libpthread.so.0 #2 0xb7c92f4e in clone () from /lib/libc.so.6 На SuSE 11.1 с glibc-2.9-2.11.1 - проблема не обнаружена На Mandriva 2009.0 с glibc-2.8-1.20080520.5.2mnb2 - проблема проявляется: (gdb) bt #0 0xb7b249b0 in ?? () from /lib/i686/librt.so.1 #1 0xb7b2723c in ?? () from /lib/i686/librt.so.1 #2 0x086c5178 in ?? () #3 0xb7b24a30 in ?? () from /lib/i686/librt.so.1 #4 0x08a5bf48 in ?? () #5 0x00000000 in ?? () Пересобрал glibc-2.9-alt4 из Сизифа для Branch 5.0 - проблема не исправилась. Branch 4.1 glibc-core-2.5.1-alt4 - проблема не проявляется. Роман, спасибо. Можно приложить сюда код, поведение которого изменилось? Created attachment 3419 [details]
Архиватор значений
Пожалуйста.
Вкладываю файл части исходника проекта OpenSCADA. Только искать там можно долго. Проблемные участки это конструктор и деструктор класса TVArchivator:
TVArchivator::TVArchivator( const string &iid, const string &idb, TElem *cf_el ) : run_st(false), prc_st(false),
tm_calc(0.0), TConfig(cf_el), m_db(idb), m_id(cfg("ID").getSd()), m_name(cfg("NAME").getSd()),
m_dscr(cfg("DESCR").getSd()), m_addr(cfg("ADDR").getSd()), m_start(cfg("START").getBd()),
m_v_per(cfg("V_PER").getRd()), m_a_per(cfg("A_PER").getId())
{
m_id = iid;
//> Create calc timer
struct sigevent sigev;
memset(&sigev,0,sizeof(sigev));
sigev.sigev_notify = SIGEV_THREAD;
sigev.sigev_value.sival_ptr = this;
sigev.sigev_notify_function = Task;
sigev.sigev_notify_attributes = NULL;
timer_create(CLOCK_REALTIME,&sigev,&tmId);
}
TVArchivator::~TVArchivator()
{
timer_delete(tmId);
}
Всё остальное непринципиально, в случае с данной проблемой, поскольку я его наглухо отглушал, а проблема проявлялась.
Особенность её ещё в том, что удаление потока в timer_delete происходит не сразу, а отложенно. Поэтому если программу завершать, то проявиться проблема не успевает, да и нагрузка снимается к тому моменту.
И если timer_delete(tmId); закомментировать, то проблема не возникает, но естественно текут ресурсы таймера.
Вообще была мысль попробовать в макет добавить с десяток потоков с имитацией рабочей нагрузки, что-бы оно проявлялось более отчётливо.
Valgrind по поводу timer_delete() постоянно сообщает такое: ==21938== ==21938== Conditional jump or move depends on uninitialised value(s) ==21938== at 0x4417324: timer_delete (in /lib/librt-2.9.so) ==21938== by 0x405C905: TArchiveS::~TArchiveS() (in /mnt/home/roman/work/OScadaD/lib/liboscada.so.0.0.10) Боюсь что я не готов отлаживать большую и сложную программу из проекта OpenSCADA. К сожалению, апстрим этого тоже не станет делать, для этого нужен test case попроще. У меня не получилось добиться повторения на тестовом прототипе, даже добавив близкую нагрузку. Похоже сказывается достаточно специфичная нагрузка. Кроме того, в компоненте где ошибка проявлялась я перешёл на независимые потоке, по объективным причинам. Поэтому откладываем на позже, может у кого такое ещё вылезет. glibc-2.10.1-alt4 Valgrind по прежнему указывает на наличие проблемы в функции timer_delete: ==5608== Thread 1: ==5608== Conditional jump or move depends on uninitialised value(s) ==5608== at 0x442BF72: timer_delete (in /lib/librt-2.10.1.so) ==5608== by 0x6AE9FD7: FSArch::ModArch::~ModArch() (in /mnt/home/roman/work/OScadaD/lib/openscada/arh_FSArch.so) ==5608== by 0x41343FD: TCntrNode::chldDel(char, std::string const&, long, int, bool) (in /mnt/home/roman/work/OScadaD/lib/liboscada.so.0.0.10) ==5608== by 0x40DB504: TSubSYS::modDel(std::string const&) (in /mnt/home/roman/work/OScadaD/lib/liboscada.so.0.0.10) ==5608== by 0x411A4F6: TModSchedul::preDisable(int) (in /mnt/home/roman/work/OScadaD/lib/liboscada.so.0.0.10) ==5608== by 0x41336D6: TCntrNode::nodeDis(long, int) (in /mnt/home/roman/work/OScadaD/lib/liboscada.so.0.0.10) ==5608== by 0x41344BA: TCntrNode::chldDel(char, std::string const&, long, int, bool) (in /mnt/home/roman/work/OScadaD/lib/liboscada.so.0.0.10) ==5608== by 0x4050525: TSYS::~TSYS() (in /mnt/home/roman/work/OScadaD/lib/liboscada.so.0.0.10) ==5608== by 0x8048D3A: main (in /mnt/home/roman/work/OScadaD/bin/openscada) |