LINUX.ORG.RU

send в сокет и EAGAIN


1

2

Привет. Какой наиболее правильный способ обработки EAGAIN ошибки send'a у неблокирующего сокета? Способ подождать n милисекунд кажется workaround'ом или обычно так и делают? Спасибо.
P.S.: Это embedded приложение, монстрообразный boost мне не нужен.

★★★★★

Последнее исправление: UVV (всего исправлений: 1)

Нет смысла ждать. Юзай блокирующие сокеты + потоки. Это вообще не ошибка, а особенность работы ядра. Если у тебя EAGAIN выбрасывается более нескольких секунд, то надо тюнить ядро/архитектуру приложения.

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

Конечно, не гарантия. Возможность записи в некий момент времени не означает возможности записи момент, когда вы решите собственно записывать. При невозможности записи нужно снова ждать.

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

Внимательно почитай выхлоп профи тут

Эм, а там есть выхлоп?

true_admin ★★★★★
()

Можно использовать какие-либо хорошие обертки типа libev. рекомендую.

vromanov ★★
()

обычно ждут доступного места в буфере сокета с помощью epoll/kevent

За использование select в 21-м веке полагается порка патч-кордом.

anonymous
()
Ответ на: комментарий от vromanov

Я не интересовался сторонними библиотеками, спасибо.

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

дорогу рвущимся прогуляться по граблям!

Таки дело не в эффективности, а в том, что он затачивался под очень старые системы.

anonymous
()
Ответ на: дорогу рвущимся прогуляться по граблям! от anonymous

Тут сверху мне ссылку дали на умный выхлоп, и там написано:

The Linux-specific epoll(7) API provides an interface that is more efficient than select(2) and poll(2) when monitoring large numbers of file descriptors.

Собсно вопрос, накуя мне тогда epoll, если select'a достаточно?

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

чтобы весело и с матерком не дебажить рандомные повреждения памяти

такой ответ вас устроит?

anonymous
()
Ответ на: комментарий от vromanov

ваше мнение, уважаемый, не может восприниматься всерьёз

Селектом пользоваться нельзя. Предельно допустимая концентрация ламеров и так превышена в разы на моём ЛОР-е. Не хватает ещё топиков «Программа упала, память испорчена... телепаты! трабуется ваша помощь».

anonymous
()
Ответ на: комментарий от vromanov

Побить массив на кусочки по FD_SETSIZE

Имхо, лучше воткнуть libev который 1) портабелен 2) гораздо более удобен чем голый select и уж тем более какой-нить epoll 3) оно само выберет подходящий бэкенд для event loop

true_admin ★★★★★
()
Последнее исправление: true_admin (всего исправлений: 1)
Ответ на: комментарий от true_admin

Я это уже предлагал выше, но ТС отказался от сторонних библиотек. А так, конечно с libev жизнь куда слаще и проще.

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

Хм, любопытно тогда отчего возник EAGAIN. В моём представлении об устройстве этого мира если сокет один и select вернул что он writable то не должно такое возникать. Я понимаю что проверять всё равно надо. Возможно, в системе есть какая-то другая паралельная сетевая активность.

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

Собсно вопрос, накуя мне тогда epoll, если select'a достаточно?

У вызовов select()/poll()/epoll() разные API. Мне больше всего нравится epoll, два других я считаю устаревшими. Но select() более портабелен. Еще select() и poll() можно использовать на старых ядрах 2.4, если нужна совместимость.

Смотри, выбирай что больше подходит.

pathfinder ★★★★
()

Вообще стоит прислушаться в людям, советующим всякие libev и boost::ASIO и прочие обертки. Потому, что если ты будешь серьезно работать с вызовами типа epoll/poll/select, ты все равно напишешь свою реализацию библиотеки-обертки с абсолютно аналогичным функционалом. Единственное преимущество, что API твоего велосипеда будет именно таким, каким хочешь, но в этом далеко не всегда есть какой-то смысл.

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

Вообще стоит прислушаться в людям, советующим всякие libev и boost::ASIO и прочие обертки.

Исправил исходный топик.

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

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

Никаких подождать N-милисекунд. Дожидаемся готовности дескриптора к записи через вызов epoll.

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

Сокет неблокирующий, у ТС вроде пока нет никаких селектов - он просто делает send, который в виду отсутствия места в буфере (или еще чего-то) возвращает EAGAIN - и ТС спрашивает что ему делать - подождать и попробовтаь снова, или еще чего-то.

Ему посоветовали селект.

А дальше дискуссия набрала обороты.

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

Все таки - если это эмбеддед, то я подозреваю что там действительно меньше 10 одновременных коннектов.

Зачем нужна зависимость от libev ? Мои маленькие любители преждевременной оптимизации.

OxiD ★★★★
()
Последнее исправление: OxiD (всего исправлений: 1)
Ответ на: комментарий от pathfinder

И я уверен - поверх надо будет делать все рано еще одну обертку для предметной области. Так что это не аргумент.

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

А дальше дискуссия набрала обороты.

Это связано с тем, что приложения, обслуживающие ввод-вывод (и не только), там где надо дожидаться определенных событий (готовность для чтения/записи, запрос на установление соединения и т. д.) более-менее гармонично могут быть написаны двумя разными путями, ну или идеологиями:

1. Опирается на многопоточность и блокирующий ввод/вывод. Ожидание достигается засыпанием процесса во множестве разных мест программы. Примером таких программ может служить любой многопоточный TCP сервер. Инфраструктура ввода/вывода «размазана» по коду.

2. Опирается на неблокирующий ввод/вывод. Может легко обслуживать множество соединений в рамках одного потока. Как правило, процесс засыпает в строго определенном месте, внутри тела процедуры, так называемого «цикла обработки сообщений». Скорее всего засыпает на этом самом вызове epoll(). Имеет ярко выраженную инфраструктуру, берущую на себя всю рутину по обслуживанию ввода/вывода и ожиданию событий.

99% программ используют одну из этих двух идеологий. Если речь идет именно о неблокирующем вводе/выводе, то само собой должно подразумеваться, что есть какая-то обособленная инфраструктура ввода/вывода; самописная или на базе какой-нибудь библиотеки типа boost::ASIO. Эта самая инфраструктура в ходе своего функционирования естественным образом должна решать проблему, которая возникла у ТС.

Выводы:

Либо у ТС какое-то маленькое простенькое приложение, от которого много не требуется, пускай вызывает usleep(). Криво, но зато работает.

Либо ТС должен работать с блокируемыми сокетами.

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

Либо ТС нашел какой-то свой, «особенный» путь. Тогда ему никто не поможет, и он должен бороться один со своими проблемами.

pathfinder ★★★★
()
Последнее исправление: pathfinder (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.