LINUX.ORG.RU

splice+pipe=EAGAIN

 ,


0

1

Добрый день

Делаю сплайс из неблокируемого сокета в пайп.
Псевдокод:


if(pipe(splice_pipe) < 0)
	{
		perror("pipe");
		return -1;
	}

pipe_size = fcntl(splice_pipe[0], F_GETPIPE_SZ))
...................
//При событии поступления данных на сокет
if((read = splice(
			sock_fd,
			NULL,
			splice_pipe[1],
			NULL,
			pipe_size - pipe_bytes_num,
			SPLICE_F_MOVE|SPLICE_F_NONBLOCK
			)) <0)
{
  perror("splice");
  return -1;
}

pipe_bytes_num += read;

Размер пайпа 65536 байт. При попытке заполнить пайп полностью splice выдает EAGAIN.
Ради шалости попробовала заведомо уменьшить на килобайт-другой значение переменной pipe_size чтобы не заполнять подзавязку - не дает результата. А вот если уменьншить pipe_size килобайт на 20, то EAGAIN не выскакивает.
Лишний пустой вызов splice очень напрягает, особенно часто это может быть если медленный читатель из пайпа, а писатель очень быстрый.

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


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

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

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

вообще EAGAIN EINTR говорят не о том что капец все пропало, а о том что операция прервана, повторите еще, но смысла ее по кругу читать нет, если это на дескрипторе сокета, то есть смысл повторно вернутся в пул и если дескриптор опять готов то попытать счастье еще раз, цпу пуллер не жрет

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

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

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

а если десятка а не двенадцать ? тоже будешь поддерживать ? правила софто девелопинга, поддерживать актуальные релизы, а то утонуть в прошлом можно, если еще пытаться как то обеспечить splice когда его в линуксе и не было вообще)))

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

ну если она это повторяет на локальном сокете...

Даже в локальный сокет данные прибывают с задержками. Я удивляюсь, почему она сначала читает, а потом смотрит FIONREAD. Ну или хотя бы после EAGAIN повторяла попытку с результатом FIONREAD.

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

про FIONREAD до чтения согласна.
завтра попробую варианты что тут обсудили на впс и локалхостах на актуальных ядрах. сегодня уже отбой) большое спасибо за советы и рекомендации

ЗЫ часто на впс вижу ядра 2.6.х

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

про FIONREAD до чтения согласна.

Я бы делал FIONREAD только в случае EAGAIN.

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