Есть программка которая берет данные и может их вывести один раз (просто через cout), а может (если установлена опция) — переодически брать данные и выводить их на экран (через ncurses).
Куски кода:
struct thread_args {
ncui *ui;
mystat *stat;
};
void loop(void* threadarg) {
thread_args *args = reinterpret_cast<thread_args *>(threadarg);
while (true) {
info = args->stat->getinfo(); // берем данные
args->ui->setinfo(info); // передаем их в ncurses gui
...
args->ui->tick(); // даем команду на отрисовку
sleep(sleep_sec);
}
int main() {
...
if (options.loop) {
mystat stat; // class откуда берутся данные
ncui ui = ncui(); // class для работы с ncurses
thread_args args;
args.ui = &ui;
args.stat = &stat;
...
pthread_create(&mythread, NULL, (void *(*) (void *)) &loop, (void *) &args);
ui.loop() // тут идет взаимодействие с пользователем через ncurses
} else {
mystat stat1;
info = stat1.getinfo();
cout << info;
...
}
}
void ncui::tick() {
pthread_mutex_lock(&tick_mutex);
... // фактическое рисование на экране через ncurses
pthread_mutex_unlock(&tick_mutex);
}
Этот код работает нормально с gcc 4.2 и 4.3.
При использовании gcc 4.4 в той же системе (ubuntu 9.10) код виснет в ncui::tick() на
pthread_mutex_lock(&tick_mutex);
При этом, все начинает работать, если просто убрать в main() дополнительный объект класса mystat:
Но это решение не подходит. Нужен и одиночный вывод в cout.
Еще помогает если убрать pthread_mutex_lock/pthread_mutex_unlock, но это тоже не подходит, т.к. tick() может дергается еще и из самого ncui.
Здравствуйте, o.palij, Вы писали:
OP>Посоветуйте — как пофиксить?
не ужели не понятно как? -- у тебя deadlock очевидно же...
ревьюить весь код работающий с данным mutexом (из того что ты привел есь только одна функция, и по ней одной только телепаты тебе смогут сказать что происходит... а они как обычно все в отпуске )
Здравствуйте, o.palij, Вы писали:
OP>Этот код работает нормально с gcc 4.2 и 4.3. OP>При использовании gcc 4.4 в той же системе (ubuntu 9.10) код виснет в ncui::tick() на
Библиотеки которые использует данная программа также пересобираются соответствующим компилятором?
(не получается так что библиотека собрана gcc 4.2 а программа в которой она используется gcc 4.4.)
У разных версий gcc могут быть различия в ABI
Здравствуйте, zaufi, Вы писали:
Z>не ужели не понятно как? -- у тебя deadlock очевидно же... Z>ревьюить весь код работающий с данным mutexом (из того что ты привел есь только одна функция, и по ней одной только телепаты тебе смогут сказать что происходит... а они как обычно все в отпуске )
Имеется в виду, что этот мьютекс может захватыватся в другом месте кроме как в tick()?
т.е. он захватывается только в ncui::tick(). этот tick() вызывается только внутри loop() и внутри ncui::loop(). Внутри ncui::loop() tick() вызывается только если нажата клавиша, чего явно не происходит.
Весь вопрос в том, почему при комментировании части кода, которые никакого отношения к ncui не имеет — все начинает работать. А так же в том, почему с gcc 4.2 и 4.3 все тоже работает.
Здравствуйте, kpcb, Вы писали:
OP>>Этот код работает нормально с gcc 4.2 и 4.3. OP>>При использовании gcc 4.4 в той же системе (ubuntu 9.10) код виснет в ncui::tick() на
K>Библиотеки которые использует данная программа также пересобираются соответствующим компилятором? K>(не получается так что библиотека собрана gcc 4.2 а программа в которой она используется gcc 4.4.) K>У разных версий gcc могут быть различия в ABI
Из стандартных библиотек используется только ncurses и pthread, каким компилятором они собирались я не знаю. Но в 9.10 по-умолчанию идет gcc 4.4, так что думаю что им. После того как начались проблемы я поставил 4.3 (просто сам компилятор безо всяких библиотек, которые уже есть в системе) и пробовал с ним.
Здравствуйте, o.palij, Вы писали:
OP>Здравствуйте, zaufi, Вы писали:
Z>>не ужели не понятно как? -- у тебя deadlock очевидно же... Z>>ревьюить весь код работающий с данным mutexом (из того что ты привел есь только одна функция, и по ней одной только телепаты тебе смогут сказать что происходит... а они как обычно все в отпуске ) OP>Имеется в виду, что этот мьютекс может захватыватся в другом месте кроме как в tick()? OP>
OP>т.е. он захватывается только в ncui::tick(). этот tick() вызывается только внутри loop() и внутри ncui::loop(). Внутри ncui::loop() tick() вызывается только если нажата клавиша, чего явно не происходит.
ок, а где этот mutex инициализируется????
гдета должен быть вызов pthread_mutex_init (из результата грепа видно что статической инициализации нет) -- где же тогда рантаймная инициализация??
Почему не понял, но помогло объявление переменной типа pthread_mutexattr_t рядом с объявлением мьютекса.
т.е. было
class ncui {
...
private:
pthread_mutex_t tick_mutex;
стало:
class ncui {
...
private:
pthread_mutex_t tick_mutex;
pthread_mutexattr_t mattr;
При этом даже не надо делять привязку атрибута к мьютексу (pthread_mutexattr_settype), хотя я на всякий случай сделал (но заработало и без этого). Кроме того попробовал все типы мьютексов — работает во всеми.
Если бы это кто-то объяснил, моему счастью не было бы границ
Здравствуйте, zaufi, Вы писали:
Z>ок, а где этот mutex инициализируется???? Z>гдета должен быть вызов pthread_mutex_init (из результата грепа видно что статической инициализации нет) -- где же тогда рантаймная инициализация??
Да. Спасибо. Это оно. Вроде уже разобрался. Если я правильно понял pthread_mutex_init — это рантаймная инициализация, а что тогда такое статическая?
Здравствуйте, o.palij, Вы писали:
OP>Здравствуйте, zaufi, Вы писали:
Z>>ок, а где этот mutex инициализируется???? Z>>гдета должен быть вызов pthread_mutex_init (из результата грепа видно что статической инициализации нет) -- где же тогда рантаймная инициализация?? OP>Да. Спасибо. Это оно. Вроде уже разобрался. Если я правильно понял pthread_mutex_init — это рантаймная инициализация, а что тогда такое статическая?
Здравствуйте, o.palij, Вы писали:
OP>Почему не понял, но помогло объявление переменной типа pthread_mutexattr_t рядом с объявлением мьютекса. OP>т.е. было OP>
OP>При этом даже не надо делять привязку атрибута к мьютексу (pthread_mutexattr_settype), хотя я на всякий случай сделал (но заработало и без этого). Кроме того попробовал все типы мьютексов — работает во всеми. OP>Если бы это кто-то объяснил, моему счастью не было бы границ
для справки: атрибуты mutex'a нужны если ты хочешь создать не дефолтный mutex (ну там например рекурсивный или с проверкой ошибок... вопщим читать маны pthread_mutexattr_setXXX). эти атрибуты нужны когда вызываешь pthread_mutex_init -- т.е. прото тупо заводить переменную такого типа бессмысленно!
из приведенного кода опять же не видно как создается экземпляр класса ncui... anyway, большенство реализаций макрухи PTHREAD_MUTEX_INITIALIZER это просто заполнение нулями полей структуры... вопщим если у тя эксемпляр ncui содвалался так, что на месте mutex'a оказывались нули то все работает блягодаря тупо везению...
MUTEX НАДО ИННИЦИАЛИЗИРОВАТЬ! равно как и атрибуты