LINUX.ORG.RU

socket() accept() close() - thread safe?


0

1

Встретил тут в одном кроссплатформенном коде (lin/bsd/win) обертку с мьютексом вокруг сокетных функций socket() accept() close().

Вопрос на кой? Впервые о таком слышу, может в венде оно не потокобезопасно?

★★★★

Смотря как написано, может чтоб два потока не открывали(писали) одновременно в один сокет, логика работа такая .

ilovewindows ★★★★★
()

обертки на мьютексах только для этих функций. для recv к примеру нет

quest ★★★★
() автор топика
Ответ на: комментарий от tailgunner

На каком-нибудь древнем Unix со STREAMS могло понадобиться.

Код 2012 года в одной крупной конторе... Помоему это то-же бред...

quest ★★★★
() автор топика
Ответ на: комментарий от quest

На каком-нибудь древнем Unix со STREAMS могло понадобиться.

Код 2012 года в одной крупной конторе...

Если его писали с расчетом на такие системы, почему нет? Но, конечно, это может быть и тупой перестраховкой.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

STREAMS это что то что было до tcp/ip ? Как я понимаю там нет функции int socket(int, int, int). Может и правда в какой то win95 socket имела в себе какую то статическую переменную и была не потокобезопасна... или это просто бредовый код)

quest ★★★★
() автор топика
Ответ на: комментарий от quest

STREAMS это что то что было до tcp/ip ?

Нет. Это идеология построения системы ввода-вывода.

Как я понимаю там нет функции int socket(int, int, int)

Там есть библиотека libsocket.a Полагаю, что где-то когда-то она была не-thread-safe.

tailgunner ★★★★★
()
Ответ на: комментарий от quest

Здесь int rc разделяемый ресурс, может быть такое , что socket уже вернул значение, то есть сокет уже занят, а rc еще не присвоено и равно NULL. В этот момент потоки переключаются и другой поток проверяет rc , оно равно NULL и поток лезет к занятому сокету, что не есть гуд.

ilovewindows ★★★★★
()
Ответ на: комментарий от ilovewindows

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

int wrapper_socket(arg)
{
    magick_locker_t magick_locker(::global_mutex);
    return socket(arg);
}
quest ★★★★
() автор топика
Ответ на: комментарий от ilovewindows

Здесь int rc разделяемый ресурс, может быть такое , что socket уже вернул значение, то есть сокет уже занят, а rc еще не присвоено и равно NULL. В этот момент потоки переключаются и другой поток проверяет rc

ЛОЛШТО? rc на стеке, как его увидит другая нить?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Сказано же «псевдокод», оригинал смотрите , чего они там закрывали.

ilovewindows ★★★★★
()
Ответ на: комментарий от ilovewindows

за исключением имени функции, списка аргументов (arg), имени умирающего мьютексодержателя, имени мьютекса - оно именно так и реализовано в две строки кода.

quest ★★★★
() автор топика
Ответ на: комментарий от quest

Угу, еще у socket один аргумент и в переделанном втором примере вообще не вижу чтобы он был закрыт.
Вообщем, точно такое же , только черное , на размер меньше и жмет.

ilovewindows ★★★★★
()
Ответ на: комментарий от ilovewindows

Так лучше?

int wrapper_socket(int a, int b, int c)
{
    magick_locker_t magick_locker(::global_mutex);
    return socket(a, b, c);
}

Кто закрыт? Это обертка функции socket() - замена ее. Такие же замены зачем то написаны для accept() и close()

quest ★★★★
() автор топика
Ответ на: комментарий от quest

ах отстаньте уже со своими записями! )))

Твой вопрос как раз об этом %)

tailgunner ★★★★★
()
Ответ на: комментарий от quest

Поясняю на примере. Сначала сокет открывается, поток «quest» туда пишет всякую лажу, которую только quest и может распарсить. Сокет от закрытия до закрытия заблокирован от других потоков. Если не блокировать, поток tailgunner может встрять в запись и добавить свою лажу, ну умничья какие-нибудь или попыки юмора. И получится ВАЩЕ ЛАЖА. Вопрос «ЗАЧЕМ?» все еще стоит ?

ilovewindows ★★★★★
()
Ответ на: комментарий от ilovewindows

Сначала сокет открывается, поток «quest» туда пишет всякую лажу

Ни в одном варианте псевдокода нет «записи всякой лажи», ты это придумал.

Вопрос «ЗАЧЕМ?» все еще стоит ?

Нет, всё уже понятно.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Надо в оригинале внимательно смотреть,без собственных искажений в п сев до кодах,по имени мьютеса,смотреть где лок ставится и где снимается. Что там автор считал разделЯемым ресурсом хрен его знает. Может и ру д имен ты,(планшет новый чего то вставляет) или задел на будущее.

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

ilovewindows ★★★★★
()
Ответ на: комментарий от ilovewindows

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

Шо, опять? Объясни мне подробно, что может не туда запомниться при переключении нити.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Работа с разделяемым потоками ресурсом должна начинаться с вызова lock и заканчиваться вызовом unlock. В первом примере между lock и unlock запись дескриптора, возвращаемого socket, идет в локальную переменную. Далее предполагается вернуть её как результат и запомнить где-то, в глобальной переменной например. Вот сразу после unlock этот поток может быть остановлен и запустится другой поток ,который полезет к тому же сокету, проверит глобальную переменную (дескриптор открытого сокета) - там ноль, решит что сеть не занята, еще раз займет этот сокет. А когда первому потоку вернется управление, он открытый вторым потоком дескриптор похерит.

ilovewindows ★★★★★
()
Ответ на: комментарий от ilovewindows

Далее предполагается вернуть её как результат и запомнить где-то, в глобальной переменной например.

Или не в глобальной.

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

И как это объясняет роль упомянутого мютекса?

И хотелось бы понять, в чем «лажа первого примера» - тот сценарий, который ты расписал, в первом примере не содержится.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Вот про этот пример речь
int wrapper_socket(arg)
{
global_mutex_lock();
int rc = socket(arg);
global_mutex_unlock();
return rc;
}

Возвращаемое значение должно где-то использоваться, иначе нафик оно. И должно хранится в переменной, она «глобальная» для всех функций которые её используют .
Мьютекс это просто флажок , занято-свободно для какого-то ресурса. В примере разделяемый ресурс дескриптор результат вызова socket и он меняется на прерываемом участке кода.

ilovewindows ★★★★★
()
Ответ на: комментарий от ilovewindows

Возвращаемое значение должно где-то использоваться, иначе нафик оно.

Еще раз: в чем лажа _примера_? Не предположительная лажа кода, использующего wrapper_socket, а именно лажа самого wrapper_socket?

И должно хранится в переменной, она «глобальная» для всех функций которые её используют .

Ничего подобного оно не должно.

tailgunner ★★★★★
()
Ответ на: комментарий от ilovewindows

Сокет от закрытия до закрытия заблокирован от других потоков.

вы не отвечаете на мой ответ! функция socket() просто возвращает новый хендл и кто куда может встрять без мухоморов совершенно не ясно. Волшебный мьютексоубиватель это класс qt:

int wrapper_socket(int a, int b, int c)
{
	QMutexLocker locker(::global_mutex);
	return socket(a, b, c);
}

заставляете выдавать все корпоративные секреты)))) вот он этот код. может он патентами защищен - патент на суперпотокобезопасные функции)

quest ★★★★
() автор топика
Ответ на: комментарий от quest

Тут же нет разблокировки, в этой функции. Проследи выполнение до разблокировки. Видимо на этом участке будет происходить присвоение глобальных переменных или другие non thread safe действия.

auto12884835
()
Ответ на: комментарий от quest

Кстати да, упустил из виду. Тогда наверное единственно возможное разумное объяснение может быть типа такого.

auto12884835
()

пообщался с автором сего... якобы он пришел к такому после того как у него в тредах не всегда socket() возвращала валидный хендл и теперь всегда так пишет в место того чтобы проверять ulimit и вообще искать баги в своем коде... так пожелаем всем нам не работать в компаниях где пишут такой код!

quest ★★★★
() автор топика
Ответ на: комментарий от tailgunner

этот же человек утверждает что open() и close() то-же нужно блокировать глобальным мьютексом потому что дословно «в windows эти функции безопасны, а в linux - нет, поскольку эти системные вызовы не блокируют таблицу дескрипторов процесса»

quest ★★★★
() автор топика
Ответ на: комментарий от quest

этот же человек утверждает что open() и close() то-же нужно блокировать глобальным мьютексом потому что дословно «в windows эти функции безопасны, а в linux - нет, поскольку эти системные вызовы не блокируют таблицу дескрипторов процесса»

Передай ему, что он лох.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

мне то-же что-то подсказывает что это забористый бред))) зато сразу прямо таки захотелось посмотреть libc/ядро чтобы увидеть конкретный код который распределяет деcкрипторы)

quest ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.