URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 9057
[ Назад ]

Исходное сообщение
"Собственные данные потока. Core Dump"

Отправлено magelan , 03-Мрт-11 13:05 
Здравствуйте.

Мой уровень программирования невысокий. Хочу разобраться с потоками. Если бы вы могли мне помочь понять почему у меня прога валиться в кору, буду безмерно вам благодарен.
И так коротко о программе. Программа слушает UDP сокет. При получении датаграмы, создается поток, в потоке создаются собственные данные, поток отсоеденяется и дальше идет работа с mysql, после чего функция потока завершается (соответственно вызываются деструкторы для уничтожения собственных даных потока.) Так вот кора получается то после 2 полученых пакетов, то после 20, то после 10, причем абсолютно в разных местах. Причем никакой коры нет если закоментировать запись в mysql. Выходит проблема именно когда идет взаимодействие с базой. дискриптор базы в начале у меня был объявлен глобально и любая функция могла вызвать запросы. Такой вариант тоже выпадал в кору, поэтому я решил дискриптор тоже сделать собственными данными потока. Результат - кора. Вот выдержки исходника.

typedef struct mysql_thread
{
    char query[BUF_SIZE];
    char *separator,*ip,*url;
    MYSQL mysqld;
}mysql_thread_data;

pthread_key_t rl_key;
pthread_once_t rl_once = PTHREAD_ONCE_INIT;

void init_DB(MYSQL *mysql_thread)
{
    if (!(mysql_real_connect(mysql_thread,setST.DBhost,setST.DBlogin,setST.DBpass,setST.DB,setST.port,setST.MySQLsock,2)))
      {
      syslog(LOG_NOTICE,"ERROR: Can not connect to mysql database.");
          exit(EXIT_FAILURE);
      }
    if (mysql_select_db(mysql_thread,setST.DB))
    {
         syslog(LOG_NOTICE,"ERROR: Can not select database.");
         exit(EXIT_FAILURE);
    }
}

void close_DB (MYSQL *mid)
{
  mysql_free_result(res);
  mysql_close(mid);
}


static void insert_DB (void * arg)
{

    mysql_thread_data *mysql_insert_var;

    зthread_once(&rl_once,dos_mysql_once_th);
    if ((mysql_insert_var=pthread_getspecific(rl_key)) == NULL )
        {
            mysql_insert_var = calloc(1,sizeof(mysql_insert_var));
            pthread_setspecific(rl_key,mysql_insert_var);
    }
    pthread_detach(pthread_self());
    init_DB(&mysql_insert_var->mysqld);
    close_DB(&mysql_insert_var->mysqld);
}
......
pthread_create(&tid,NULL,(void *)&insert_DB,(void *) msg);

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

У меня только одно предположение - я неправильно организовываю собственные данные потока.
Наставьте на пусть истинный.

Спасибо.


Содержание

Сообщения в этом обсуждении
"Собственные данные потока. Core Dump"
Отправлено magelan , 03-Мрт-11 13:33 
вот такой эксперимент я провел. после
pthread_detach(pthread_self());
printf ("thread %d\n",mysql_insert_var);

просто распечатываю указатель.
так вот
thread 674513532
thread 674513532
thread 674513532
thread 674514036
thread 674514540
thread 674515044

первые 3 указателя одинаковые.
значит получается что 3 потока используют один и те же данные. В том числе и дискриптор мускуля. А не из-за этого ли кора?


"Собственные данные потока. Core Dump"
Отправлено sm00th1980 , 03-Мрт-11 14:03 
Коллега, а чем был обусловлен выбор C-подобных языков для работы с тредами и сетевыми вещами? Просто работа с указателями та ещё пестня...если честно. Никогда нельзя быть в итоге уверенным что где-то нет утечки :(

Моё скромное ИМХО, если нужно работать с потоками и разбирать UDP - по посмотрите в сторону Python/Twisted - как вариант или Erlang тоже отлично подойдёт.


"Собственные данные потока. Core Dump"
Отправлено magelan , 03-Мрт-11 14:08 
> Коллега, а чем был обусловлен выбор C-подобных языков для работы с тредами
> и сетевыми вещами? Просто работа с указателями та ещё пестня...если честно.
> Никогда нельзя быть в итоге уверенным что где-то нет утечки :(
> Моё скромное ИМХО, если нужно работать с потоками и разбирать UDP -
> по посмотрите в сторону Python/Twisted - как вариант или Erlang тоже
> отлично подойдёт.

Знаю чуть-чуть С поэтому выбрал именно его.

Как я и предоплогал разные потоки обращаются к одним данным

printf ("thread %d-%d\n",mysql_insert_var,pthread_self());
через pthread_self() я получаю идентификатор потока. Они разные :(

thread 674513532-674328896
thread 674513532-674328256
thread 674513532-674327936
thread 674513532-674327616

подскажите в чем косяк и как исправить.


"Собственные данные потока. Core Dump"
Отправлено pavlinux , 03-Мрт-11 14:18 
> Как я и предоплогал разные потоки обращаются к одним данным
> подскажите в чем косяк и как исправить.

Нужен ГОЛ!!! Нужен ГОЛ!!! Нужен ГОЛ!!!.... Тфу,
Нужен МУТЕХ !!!Нужен МУТЕХ !!!Нужен МУТЕХ !!!


"Собственные данные потока. Core Dump"
Отправлено magelan , 03-Мрт-11 14:30 
>> Как я и предоплогал разные потоки обращаются к одним данным
>> подскажите в чем косяк и как исправить.
> Нужен ГОЛ!!! Нужен ГОЛ!!! Нужен ГОЛ!!!.... Тфу,
> Нужен МУТЕХ !!!Нужен МУТЕХ !!!Нужен МУТЕХ !!!

минуточку.
мутех приведет к тому что только один потом будет работать все остальные ожидать.
я же хотел что бы все делалось параллельно.
Ведь есть же такое понятие как thread-specific data - есть. есть способ ее реализовать - есть. Ну так причем тут мутекс? Ведь только первые несколько записей лажанутые остальыне нормальные. Думаю без мутекса тут можно обойтись. Вопрос что я сделал неправильно.


"Собственные данные потока. Core Dump"
Отправлено pavlinux , 03-Мрт-11 14:56 
>>> Как я и предоплогал разные потоки обращаются к одним данным
>>> подскажите в чем косяк и как исправить.
>> Нужен ГОЛ!!! Нужен ГОЛ!!! Нужен ГОЛ!!!.... Тфу,
>> Нужен МУТЕХ !!!Нужен МУТЕХ !!!Нужен МУТЕХ !!!
> минуточку.
> мутех приведет к тому что только один потом будет работать все остальные
> ожидать.

1. можно юзать pthread_rwlock
2. Где функция dos_mysql_once_th(), и pthread_key_create()
3. pthread_self() возвращает pthread_t он же long, спецификатор для printf - %ld

Ну и самое интересное - при обращении по одному разделяемому ключу, разные потоки будут получать доступ к разным данным.

Прям уж так нужна pthread_setspecific() ???
Вариантов много, нужен весь код иль упрощённая версия, а так можно гадать долго.


Кстати, скорее всего команда  pthread_setspecific(rl_key,mysql_insert_var);
меняет не одну и туже переменную rl_key, а уже свою :)


"Собственные данные потока. Core Dump"
Отправлено magelan , 03-Мрт-11 15:11 
> 1. можно юзать pthread_rwlock

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

> 2. Где функция dos_mysql_once_th(), и pthread_key_create()

static void dos_mysql_th_destructor (void *ptr)
{
    free(ptr);
}

static void dos_mysql_once_th (void)
{
    pthread_key_create(&rl_key,dos_mysql_th_destructor);
}

> 3. pthread_self() возвращает pthread_t он же long, спецификатор для printf - %ld

от этого ничего не изменилось. вывод остался прежним. но спасибо за информацию.

> Ну и самое интересное - при обращении по одному разделяемому ключу, разные
> потоки будут получать доступ к разным данным.

тут не понял.

> Прям уж так нужна pthread_setspecific() ???
> Вариантов много, нужен весь код иль упрощённая версия, а так можно гадать
> долго.

насколько я понял pthread_setspecific() это ключевая команда. без нее не будет своих даных у каждого потока.

> Кстати, скорее всего команда  pthread_setspecific(rl_key,mysql_insert_var);
> меняет не одну и туже переменную rl_key, а уже свою :)

маловероятно. rl_key объявлена как глобальная. а потоки разделяют между собой все глобальные переменные процесса.


"Собственные данные потока. Core Dump"
Отправлено pavlinux , 03-Мрт-11 15:22 
>> 1. можно юзать pthread_rwlock
> насколько я понимаю, тогда мне прийдется где-то хранить данные которые приходят по
> UDP. Так как буфер для них будет блокироваться длязаписи, а ведь
> это UDP, там никто ждать не будет - не збарл датаграму
> она пропала.

А нафига тогда многотредовость? :)

Ну ладно, две нити - одна слушает UDP другая пишет в SQL


"Собственные данные потока. Core Dump"
Отправлено magelan , 03-Мрт-11 15:52 
>>> 1. можно юзать pthread_rwlock
>> насколько я понимаю, тогда мне прийдется где-то хранить данные которые приходят по
>> UDP. Так как буфер для них будет блокироваться длязаписи, а ведь
>> это UDP, там никто ждать не будет - не збарл датаграму
>> она пропала.
> А нафига тогда многотредовость? :)

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

ну а с другой стороны. да пофигу UDP или еще что-то другое, вот у меня не работает - хочу разобраться.


"Собственные данные потока. Core Dump"
Отправлено pavlinux , 03-Мрт-11 16:13 
>[оверквотинг удален]
>>> насколько я понимаю, тогда мне прийдется где-то хранить данные которые приходят по
>>> UDP. Так как буфер для них будет блокироваться длязаписи, а ведь
>>> это UDP, там никто ждать не будет - не збарл датаграму
>>> она пропала.
>> А нафига тогда многотредовость? :)
> потому что датаграмы валяться огромным потоком.
> что бы обойтись без потерь решил сделать ставку на потоки. поток получил
> датаграму и дальше себе пишет в мускуль, параллельно висят еще несколько
> потоков и делают тоже самое. Главное максимально быстро забрать датаграму что
> бы не потерять.

Ну ладно, дело ваше...  Тока не пойму, как можно из одного сокета читать параллельно.

> ну а с другой стороны. да пофигу UDP или еще что-то другое,
> вот у меня не работает - хочу разобраться.

Дай всю коду, или упрощенный вариант.
Всё же pthread_key_t редкостный вариант. :)


"Собственные данные потока. Core Dump"
Отправлено pavlinux , 03-Мрт-11 16:34 
ЁЙо...

static pthread_key_t rl_key;
static pthread_once_t rl_once = PTHREAD_ONCE_INIT;


"Собственные данные потока. Core Dump"
Отправлено magelan , 03-Мрт-11 19:07 
> ЁЙо...
> static pthread_key_t rl_key;
> static pthread_once_t rl_once = PTHREAD_ONCE_INIT;

ничего это не изменило :(

но зато я выяснил что и мускуля это не имеет отношение. Кора получается просто доступе к mysql_insert_var из функции insert_DB.
Что-то я намутил одно значно.


"__thread"
Отправлено Вова , 03-Мрт-11 18:37 
Используйте  __thread вместо работы с pthread key, весьма облегчает.

http://gcc.gnu.org/onlinedocs/gcc/Thread_002dLocal.html

Ну а вообще без исходного кода трудно судить.


"__thread"
Отправлено magelan , 03-Мрт-11 19:09 
> Используйте  __thread вместо работы с pthread key, весьма облегчает.
> http://gcc.gnu.org/onlinedocs/gcc/Thread_002dLocal.html
> Ну а вообще без исходного кода трудно судить.

Мне очень жаль но мой уровень не позволят пока оценить все преимущества __thread.

Завтра попробую сделать облегченный код без лабуды с UDP, что бы и самому было проще понять что к чему.


"__thread"
Отправлено pavlinux , 03-Мрт-11 19:37 
>> Используйте  __thread вместо работы с pthread key, весьма облегчает.
>> http://gcc.gnu.org/onlinedocs/gcc/Thread_002dLocal.html
>> Ну а вообще без исходного кода трудно судить.
> Мне очень жаль но мой уровень не позволят пока оценить все преимущества
> __thread.
> Завтра попробую сделать облегченный код без лабуды с UDP, что бы и
> самому было проще понять что к чему.

Кора из-за pthread_detach(pthread_self());


"__thread"
Отправлено magelan , 04-Мрт-11 10:00 
>>> Используйте  __thread вместо работы с pthread key, весьма облегчает.
>>> http://gcc.gnu.org/onlinedocs/gcc/Thread_002dLocal.html
>>> Ну а вообще без исходного кода трудно судить.
>> Мне очень жаль но мой уровень не позволят пока оценить все преимущества
>> __thread.
>> Завтра попробую сделать облегченный код без лабуды с UDP, что бы и
>> самому было проще понять что к чему.
> Кора из-за pthread_detach(pthread_self());

нет. я пробовал и без него. Добавлял pthread_join. Всеравно кора. Сегодня сделаю упрощенный вид программки только с потоками, а там будет видно. Дело в том что потоки программирую первый раз. Да и вообще программирую после перерыва лет 10 наверное. Так что всякие тупости это не случайность,а мой стиль программирования :)


"__thread"
Отправлено pavlinux , 04-Мрт-11 13:37 
> всякие тупости это не случайность,а мой стиль программирования :)

На bash.org  срочно! :)



"Собственные данные потока. Core Dump"
Отправлено pavlinux , 03-Мрт-11 20:26 
>[оверквотинг удален]
> так вот
> thread 674513532
> thread 674513532
> thread 674513532
> thread 674514036
> thread 674514540
> thread 674515044
> первые 3 указателя одинаковые.
> значит получается что 3 потока используют один и те же данные. В
> том числе и дискриптор мускуля. А не из-за этого ли кора?

Короча скажи спасибо писателям glibc и ядра.

Добавь в функцию нити sleep(10); и посмотри на указатели приватных данных :)

----
Вот так без sleep();

НОМЕР      pthread_self()   адрес структуры    
----------------------------------------------
Thread[0]: 140737346094848 @ address[0x6054c0]
Thread[2]: 140737329309440 @ address[0x603180]
Thread[3]: 140737320916736 @ address[0x603b20]
Thread[4]: 140737310336768 @ address[0x603a30]
Thread[5]: 140737301944064 @ address[0x603a50]
Thread[1]: 140737337702144 @ address[0x603160]
Thread[6]: 140737293551360 @ address[0x603160]
Thread[7]: 140737346094848 @ address[0x603160]
Thread[8]: 140737346094848 @ address[0x603160]

а вот так со sleep(10)

Thread[0]: 140390059624192 @ address[0x60d4c0]
Thread[1]: 140390051231488 @ address[0x60b250]
Thread[2]: 140390042838784 @ address[0x60b290]
Thread[4]: 140390026053376 @ address[0x60b3d0]
Thread[6]: 140390017660672 @ address[0x60b650]
Thread[3]: 140390034446080 @ address[0x60b270]
Thread[5]: 140389883442944 @ address[0x60b510]
Thread[7]: 140390009267968 @ address[0x60b9a0]
Thread[8]: 140389931546368 @ address[0x60bae0]
Thread[9]: 140389923153664 @ address[0x60b670]


"Собственные данные потока. Core Dump"
Отправлено magelan , 04-Мрт-11 10:02 
> Добавь в функцию нити sleep(10); и посмотри на указатели приватных данных :)

делал я это уже.
действительно с адресацией ситуация исправилась, но кора не пропала.


"Собственные данные потока. Core Dump"
Отправлено q , 04-Мрт-11 10:06 
mysql_init и
mysql_thread_init


"Собственные данные потока. Core Dump"
Отправлено magelan , 07-Мрт-11 12:53 
Как оказалось проблем неколько с этой корой.
Первая как и предпологалось при доступе к мускулю. А вот вторая... Я парсил строки. Использовал strtok. И вот он, зараза, делал мне кору. Переписал парс на указателях, тоесть ищу символ смещаю указатели присваиваю и т.д. И эта кора пропала. Но с мускулем проблема так и осталась. На сайте мускуля написано

The thread-safe client library, libmysqlclient_r, is thread-safe per connection. You can let two threads share the same connection with the following caveats:

...
If you want to use multiple threads on the same connection, you must have a mutex lock around your pair of mysql_query() and mysql_store_result() calls. Once mysql_store_result() is ready, the lock can be released and other threads may query the same connection.
....

ключевое слово on the same connection. Дискриптов мускуля я сделал собственонстью потока. И каждый поток у меня открывает отедльный конект к мускулю. Но кора от этого не пропала. На сайте мускуля рекомендуют использовать мутекс. Видимо прийдется последовать их совету.


"Собственные данные потока. Core Dump"
Отправлено ImPressed , 23-Мрт-11 17:53 
>[оверквотинг удален]
> ...
> If you want to use multiple threads on the same connection, you
> must have a mutex lock around your pair of mysql_query() and
> mysql_store_result() calls. Once mysql_store_result() is ready, the lock can be released
> and other threads may query the same connection.
> ....
> ключевое слово on the same connection. Дискриптов мускуля я сделал собственонстью потока.
> И каждый поток у меня открывает отедльный конект к мускулю. Но
> кора от этого не пропала. На сайте мускуля рекомендуют использовать мутекс.
> Видимо прийдется последовать их совету.

в многопоточных приложениях вместо strtok настоятельно рекомендуется пользовать реентрантную strtok_r(). man strtok_r() вам в помощь и не изобретайте велосипеды=)

я уже вставал на эти грабли с strtok() и прочими не реентрантыми функциями в многопоточке.


"Собственные данные потока. Core Dump"
Отправлено pavlinux , 27-Мрт-11 15:04 
> На сайте мускуля рекомендуют использовать мутекс.
> Видимо прийдется последовать их совету.

https://www.opennet.ru/openforum/vsluhforumID9/9057.html#4

=)



"Собственные данные потока. Core Dump"
Отправлено Вова , 28-Мрт-11 18:44 
>> На сайте мускуля рекомендуют использовать мутекс.
>> Видимо прийдется последовать их совету.
> https://www.opennet.ru/openforum/vsluhforumID9/9057.html#4
> =)

совет неверный.


"Собственные данные потока. Core Dump"
Отправлено фуфик , 28-Мрт-11 22:07 
>>> На сайте мускуля рекомендуют использовать мутекс.
>>> Видимо прийдется последовать их совету.
>> https://www.opennet.ru/openforum/vsluhforumID9/9057.html#4
>> =)
> совет неверный.

Нет такой функции.


"Собственные данные потока. Core Dump"
Отправлено guest , 29-Мрт-11 10:05 
> Наставьте на пусть истинный.

Посмотрите внимательно на свой код:
---
mysql_thread_data *mysql_insert_var;

mysql_insert_var = calloc(1,sizeof(mysql_insert_var));
---

ЗЫ: Вова вам правильно говорит, используйте __thread