gcc 4.4 и pthreads
От: o.palij  
Дата: 28.04.10 18:51
Оценка:
Доброго дня!

Есть программка которая берет данные и может их вывести один раз (просто через 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:

   else {
      mystat stat1;
      info = stat1.getinfo();
      cout << info;
      ...
   }


Но это решение не подходит. Нужен и одиночный вывод в cout.
Еще помогает если убрать pthread_mutex_lock/pthread_mutex_unlock, но это тоже не подходит, т.к. tick() может дергается еще и из самого ncui.

Посоветуйте — как пофиксить?
Re: gcc 4.4 и pthreads
От: zaufi Земля  
Дата: 29.04.10 01:45
Оценка:
Здравствуйте, o.palij, Вы писали:

OP>Посоветуйте — как пофиксить?


не ужели не понятно как? -- у тебя deadlock очевидно же...
ревьюить весь код работающий с данным mutexом (из того что ты привел есь только одна функция, и по ней одной только телепаты тебе смогут сказать что происходит... а они как обычно все в отпуске )
Re: gcc 4.4 и pthreads
От: kpcb Россия  
Дата: 29.04.10 03:19
Оценка:
Здравствуйте, 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
Re[2]: gcc 4.4 и pthreads
От: o.palij  
Дата: 29.04.10 05:27
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>не ужели не понятно как? -- у тебя deadlock очевидно же...

Z>ревьюить весь код работающий с данным mutexом (из того что ты привел есь только одна функция, и по ней одной только телепаты тебе смогут сказать что происходит... а они как обычно все в отпуске )
Имеется в виду, что этот мьютекс может захватыватся в другом месте кроме как в tick()?
$ grep tick_mutex *
ncui.cpp:   pthread_mutex_lock(&tick_mutex);
ncui.cpp:   pthread_mutex_unlock(&tick_mutex);
ncui.hpp:      pthread_mutex_t tick_mutex;

т.е. он захватывается только в ncui::tick(). этот tick() вызывается только внутри loop() и внутри ncui::loop(). Внутри ncui::loop() tick() вызывается только если нажата клавиша, чего явно не происходит.

Я приводил функцию к такому виду:
void ncui::tick() {
   cout << "TICK0" << endl;
   pthread_mutex_lock(&tick_mutex);
   cout << "TICK1" << endl;
   print();
   cout << "TICK2" << endl;
   pthread_mutex_unlock(&tick_mutex);
   cout << "TICK3" << endl;
}


при запуске один раз выводится TICK0 и все.

Весь вопрос в том, почему при комментировании части кода, которые никакого отношения к ncui не имеет — все начинает работать. А так же в том, почему с gcc 4.2 и 4.3 все тоже работает.
Re[2]: gcc 4.4 и pthreads
От: o.palij  
Дата: 29.04.10 05:35
Оценка:
Здравствуйте, 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 (просто сам компилятор безо всяких библиотек, которые уже есть в системе) и пробовал с ним.
Re[3]: gcc 4.4 и pthreads
От: zaufi Земля  
Дата: 29.04.10 10:47
Оценка: +1
Здравствуйте, o.palij, Вы писали:

OP>Здравствуйте, zaufi, Вы писали:


Z>>не ужели не понятно как? -- у тебя deadlock очевидно же...

Z>>ревьюить весь код работающий с данным mutexом (из того что ты привел есь только одна функция, и по ней одной только телепаты тебе смогут сказать что происходит... а они как обычно все в отпуске )
OP>Имеется в виду, что этот мьютекс может захватыватся в другом месте кроме как в tick()?
OP>
OP>$ grep tick_mutex *
OP>ncui.cpp:   pthread_mutex_lock(&tick_mutex);
OP>ncui.cpp:   pthread_mutex_unlock(&tick_mutex);
OP>ncui.hpp:      pthread_mutex_t tick_mutex;
OP>

OP>т.е. он захватывается только в ncui::tick(). этот tick() вызывается только внутри loop() и внутри ncui::loop(). Внутри ncui::loop() tick() вызывается только если нажата клавиша, чего явно не происходит.

ок, а где этот mutex инициализируется????
гдета должен быть вызов pthread_mutex_init (из результата грепа видно что статической инициализации нет) -- где же тогда рантаймная инициализация??
Re: gcc 4.4 и pthreads
От: o.palij  
Дата: 29.04.10 10:58
Оценка:
Почему не понял, но помогло объявление переменной типа 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), хотя я на всякий случай сделал (но заработало и без этого). Кроме того попробовал все типы мьютексов — работает во всеми.
Если бы это кто-то объяснил, моему счастью не было бы границ
Re[4]: gcc 4.4 и pthreads
От: o.palij  
Дата: 29.04.10 13:24
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>ок, а где этот mutex инициализируется????

Z>гдета должен быть вызов pthread_mutex_init (из результата грепа видно что статической инициализации нет) -- где же тогда рантаймная инициализация??
Да. Спасибо. Это оно. Вроде уже разобрался. Если я правильно понял pthread_mutex_init — это рантаймная инициализация, а что тогда такое статическая?
Re[5]: gcc 4.4 и pthreads
От: zaufi Земля  
Дата: 29.04.10 13:27
Оценка:
Здравствуйте, o.palij, Вы писали:

OP>Здравствуйте, zaufi, Вы писали:


Z>>ок, а где этот mutex инициализируется????

Z>>гдета должен быть вызов pthread_mutex_init (из результата грепа видно что статической инициализации нет) -- где же тогда рантаймная инициализация??
OP>Да. Спасибо. Это оно. Вроде уже разобрался. Если я правильно понял pthread_mutex_init — это рантаймная инициализация, а что тогда такое статическая?

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
Re[6]: gcc 4.4 и pthreads
От: o.palij  
Дата: 29.04.10 13:33
Оценка:
Здравствуйте, zaufi, Вы писали:

OP>>Если я правильно понял pthread_mutex_init — это рантаймная инициализация, а что тогда такое статическая?


Z>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


А. Ясно. Я так сначала и хотел, но у меня мьютекс это член класса, его не проинициализируешь.
В общем, спасибо. Все работает.
Re[2]: gcc 4.4 и pthreads
От: zaufi Земля  
Дата: 29.04.10 13:39
Оценка:
Здравствуйте, o.palij, Вы писали:

OP>Почему не понял, но помогло объявление переменной типа pthread_mutexattr_t рядом с объявлением мьютекса.

OP>т.е. было
OP>
OP>class ncui {
OP>   ...
OP>   private:
OP>      pthread_mutex_t tick_mutex;
OP>

OP>стало:
OP>
OP>class ncui {
OP>   ...
OP>   private:
OP>      pthread_mutex_t tick_mutex;
OP>      pthread_mutexattr_t mattr;
OP>

OP>При этом даже не надо делять привязку атрибута к мьютексу (pthread_mutexattr_settype), хотя я на всякий случай сделал (но заработало и без этого). Кроме того попробовал все типы мьютексов — работает во всеми.
OP>Если бы это кто-то объяснил, моему счастью не было бы границ

для справки: атрибуты mutex'a нужны если ты хочешь создать не дефолтный mutex (ну там например рекурсивный или с проверкой ошибок... вопщим читать маны pthread_mutexattr_setXXX). эти атрибуты нужны когда вызываешь pthread_mutex_init -- т.е. прото тупо заводить переменную такого типа бессмысленно!

из приведенного кода опять же не видно как создается экземпляр класса ncui... anyway, большенство реализаций макрухи PTHREAD_MUTEX_INITIALIZER это просто заполнение нулями полей структуры... вопщим если у тя эксемпляр ncui содвалался так, что на месте mutex'a оказывались нули то все работает блягодаря тупо везению...

MUTEX НАДО ИННИЦИАЛИЗИРОВАТЬ! равно как и атрибуты
Re[7]: gcc 4.4 и pthreads
От: ArtDenis Россия  
Дата: 30.04.10 11:55
Оценка:
Здравствуйте, o.palij, Вы писали:

OP>А. Ясно. Я так сначала и хотел, но у меня мьютекс это член класса, его не проинициализируешь.


А как же список инициализации в конструкторе?
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.