Несколько потоков в одной функции

Автор mihail_1, 04 июля 2012, 17:04:28

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

mihail_1

Могут ли разные потоки в одной функции портить локальные переменные друг друга в ней?

qupl

Мммм, а что подразумевается под несколькими потоками в одной функции?
Несколько потоков в одном приложении, одновременно обращающиеся/изменяющие к одним и тем же переменным вполне могут их "портить". Опять же, какой язык программирования? Лучше пример кода показать.

mihail_1

Приложение одно. Язык Си. Потоков два. Вызывают одну функцию. Через непостоянное количество вызовов происходит ошибка сегментации. (если поток один ошибка ни разу не происходила).

Olej

#3
Цитата: mihail_1 от 04 июля 2012, 20:45:17
Приложение одно. Язык Си. Потоков два. Вызывают одну функцию. Через непостоянное количество вызовов происходит ошибка сегментации. (если поток один ошибка ни разу не происходила).
Элементарно (может).
см. http://rus-linux.net/nlib.php?name=/MyLDP/BOOKS/Linux-tools/index.html - там в последней части есть достаточно примеров.
Или - http://www.books.ru/search.php?s[query]=QNX&x=0&y=0&s[go]=1&s[type_of_addon]=all:

(где-то была ссылка для скачивания книги, попадётся - сброшу).

P.S. вот здесь: http://www.flibusta.net/a/36261

mihail_1

Последняя ссылка к сожалению не живая, а из первой я не все понял.

То что общая глобальная переменная может портится, это понятно. А могут ли портится локальные переменные функции (и вызываемых из нее функций)? и области памяти выделенные malloc, на которые указывают локальные переменные?

qupl

mihail_1,  без примера кода вопрос можно обсуждать бесконечно.

mihail_1

Пример в три тысячи строк не удобен для форума, да похоже и не нужен - все ошибки в библиотечных функциях.
Одна из библиотек для работы с mysql. Его нельзя многопоточно?! (каждый поток коннектится самостоятельно используя свой список переменных)
А вот как узнать что из libc-2.7.so не поддерживает многопоточности совсем не понятно.

Olej

Цитата: mihail_1 от 24 июля 2012, 18:43:15
Пример в три тысячи строк не удобен для форума, да похоже и не нужен - все ошибки в библиотечных функциях.
1. всегда можно смоделировать пример в 10 строк который показывает проблему.

2. я за много лет ещё не встречал ни одного ни коллеги ни студента, которые бы не утверждали, что тупые не они, а "библиотечные функции"  ;D 

Цитата: mihail_1 от 24 июля 2012, 18:43:15
Одна из библиотек для работы с mysql. Его нельзя многопоточно?! (каждый поток коннектится самостоятельно используя свой список переменных)
А вот как узнать что из libc-2.7.so не поддерживает многопоточности совсем не понятно.

3. в стандартах POSIX и в описаниях библиотечных функций всегда указывается thread-safe ... или нет.
Вдумчиво читаем матчасть  ;)

mihail_1

#8
 1 - смоделировать проблему можно когда ее знаешь, а когда через пару часов работы трех тысяч строк с 33 потоками вылезает segmentation fault, не совсем ясно что моделировать.
2 - почитайте высказывания о функции iconv, которая вместо возвращения кода ошибки вызывает аварийный останов программы. (я как и многие помучавшись заменил ее своей версией - хоть эта часть программы больше не глючит, а проблемы с ней были выявлены еще в однопоточном тестировании)
3 - это похоже действительно полезная часть ответа, но посмотрев для функций malloc, printf, sprintf, atoi в манах posix на opennet я ни в одном из описаний не нашел слова thread.
Я не в том смотрю описания функций?

Сообщение объединено: 25 июля 2012, 22:10:01

Может кто даст ссылочку где "в стандартах POSIX и в описаниях библиотечных функций всегда указывается thread-safe ... или нет".

Olej

Цитата: mihail_1 от 25 июля 2012, 17:32:253 - это похоже действительно полезная часть ответа, но посмотрев для функций malloc, printf, sprintf, atoi в манах posix на opennet я ни в одном из описаний не нашел слова thread.
Я не в том смотрю описания функций?
Сообщение объединено: Вчера в 22:10:01Может кто даст ссылочку где "в стандартах POSIX и в описаниях библиотечных функций всегда указывается thread-safe ... или нет".

во-первых, я говорил не про man, а про стандарт POSIX: man-ы пишут любители, POSIX пишут профессионалы - очень большая разница. 

вот здесь в обсуждении есть ссылки на сами тексты стандарта POSIX.
особенно вам может быть интересен там раздел Rationale.

очень много примечаний о thread-safe в описаниях библиотек ОС QNX и Solaris ... главы из этих описаний можете в интернет найти.
вот ссылка на книгу, что я показывал выше: http://www.flibusta.net/a/36261 - она писалась (проверялась) на QNX, там есть много о thread-safe
(если вы о этой ссылке говорите "битая", то это неправда, я только-что проверил, вот вам совсем прямая ссылка: http://www.flibusta.net/b/129432)

многие функции и так понятны, что они не thread-safe: которые содержат satic данные в себе, возвращают побочный эффект через параметры и т.д.
часто такие функции находятся в самых неожиданных местах, например, несколько функций в строчной библиотеке str*() - куда уж проще!

если вы минимально дружите с примитивами синхронизации (хоть с самыми элементраными), то и работу с not thread-safe функциями можете сделать безопасной, кроме того, расстановкой примитивов синхронизации на фрагменты вашего огромного кода, который вас так пугает ;), вы можете легко локализлвать место SIGSEGV.


mihail_1

Делать безопасными not thread-safe функции синхронизацией почти бессмысленно. С тем же успехом можно оставить один поток. В коде в основном работа со строками и вызовы mysql. (имеется много ядер и много дисков - чтобы всех загрузить сделано много потоков, а если потоки будут работать поочереди зачем они?)
Для части функций видимо напишу свои аналоги, что с делать mysql пока непонятно.

Olej

Цитата: mihail_1 от 27 июля 2012, 21:28:04
Делать безопасными not thread-safe функции синхронизацией почти бессмысленно. С тем же успехом можно оставить один поток.
Абсолютное непонимание принципов параллелизма и синхронизации!

Цитата: mihail_1 от 27 июля 2012, 21:28:04
В коде в основном работа со строками и вызовы mysql. (имеется много ядер и много дисков - чтобы всех загрузить сделано много потоков, а если потоки будут работать поочереди зачем они?)
В хорошо прописанном коде синхронизируются минимальные критические секции (которых может быть и весьма много), достижение которых одновременно имеет обычно весьма малую вероятность.

Посмотрите вот это: Параллелизм и синхронизация - это внутри ядра Linux, не совсем то, но там можно видеть элементы того, о чём я говорю.


mihail_1

==16927== Thread 2:
==16927== Syscall param socketcall.recvfrom(buf) points to unaddressable byte(s)
==16927==    at 0x530ABA1: recv (in /lib/libpthread-2.7.so)

        l=recv(sock,&buf_work[l_buf],max_buf-1-l_buf,0);
        if(l>0)
        {
          l_buf+=l;
        }
        if(l==0)break;

Шансов передать плохой указатель или длинну нет, но ошибка есть (хотя 1 на примкрно 100000 вызовов)
приведенный код выполняется одним потоком в многопоточном приложении, использует глобальные и свои внутренние переменные.
Что исправлять?

qupl

mihail_1
1) следить за выходом за пределы буфера
2) проверить начальную инициализацию переменных
3) проверить, что не бывает ситуации когда под буфер не выделено памяти
4) ит.д.

mihail_1

буфер выделяется один раз в начале до запуска потока
l_buf обнуляется при установке каждого соединения
max_buf константа
и кроме того зачем-то есть
EBADF
Аргумент s является неверным дескриптором.
ENOTSOCK
Аргумент s не является сокетомАргумент s является неверным дескриптором
EFAULT
Указатель на приемный буфер указывает вне адресного пространства процесса.
EINVAL
Передан неверный аргумент.