LINUX.ORG.RU

POLLHUP и POLLOUT одновременно в revents

 ,


0

2

Приветствую.

Использую poll для простецкого rtsp сервера, все работает, пока не начинаю отправлять снимки через mqtt/paho, оба подключения TCP (включая rtp).

ИИ пишет что никак не может быть одновременно, но десятичное значение revents я вижу 20

Что может быть?

★★★★

Какую проблему решаешь?

POLLHUP считай за разновидность POLLIN. То есть если хочешь проверить неблокирующее чтение - ставишь POLLIN events и проверяешь наличие POLLIN|POLLHUP в revents. Если запись - ставишь POLLOUT в events и проверяешь POLLOUT|POLLERR в revents.

POLLHUP и POLLERR в основном возвращаются на закрытый сокет, но документация на этот счёт мутная, надеяться что в разных ОС (linux, freebsd, solaris итд) оно ведёт себя одинаково, включая установку POLLIN/POLLOUT при закрытом сокете, я бы не стал. Стратегия как описано выше вроде работает норм.

Конкретно линукс при закрытом соединении ставит POLLHUP, POLLERR, POLLOUT но не POLLIN - на тот момент когда я давно это проверял.

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

ставишь POLLOUT в events и проверяешь POLLOUT|POLLERR в revents

так и делаю, но приходит помимо POLLOUT еще и POLLHUP, после чего по аналогии с ffserver от ffmpeg закрываю соединение.

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

как я понимаю getsockopt мне нужно проверить всех дескрипторов, чтобы найти где ошибка!?

wolverin ★★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от Ja-Ja-Hey-Ho

Смотри в сторону настройки max_inflight_messages_set на клиенте.

Set the maximum number of messages with QoS>0 that can be part way through their network flow at once.

Defaults to 20. Increasing this value will consume more memory but can increase throughput.

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

«неработа» заключается в том, что ртсп сервер при вызове poll получает в revents значение 20 десятичное, что означает флаги POLLHUP и POLLOUT, что делать с этим?

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

Если тебя интересует только запись в сокет то POLLHUP проверять не надо. POLLHUP это чтение.

как я понимаю getsockopt мне нужно проверить всех дескрипторов, чтобы найти где ошибка!?

Какая ошибка? POLLHUP это не ошибка, это значит что с той стороны больше ничего не будут присылать в этот сокет. Повторяю, POLLHUP имеет смысл проверять только вместе с POLLIN, когда тебя интересует POLLIN.

всех дескрипторов

poll проверяет вполне конкретный дескриптор, POLLHUP относится именно к нему. При чём тут какие-то другие дескрипторы я не понял.

firkax ★★★★★
()

Может это какой-то фокус с частичным закрытием сокета? На удаленной стороне закрыли свою передачу, но вполне готовы ещё принимать данные.

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

Да фокус, но зачем и почему и совпадает с передачей «мктт сообщения» через стороннюю либу

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

А и да поллин я тоже выставляю, команды ртсп же приходят, хенг-ап правда не для этого дескриптора

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

Вопрос больше в том, что можно несколько часов смотреть видео, но стоит появиться ещё одному потоку работающего с сетью и вдруг приходят 2 как пишет ИИ исключающие события, причем в варианте с большой нагрузкой на ЦПУ это почти регулярно, а без много реже, как будто сама ОС вдруг решает на чем то экономить.

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

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

А ещё более важно - что если хенг-ап все таки не зря проверяется ) и убирать его не нужно, а нужно проверить что то еще

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

Там и не должно быть никаких ошибок, повторяю. Ещё раз, POLLHUP это разновидность POLLIN. Он, как и POLLIN, означает, что следующий вызов recv/read не будет блокироваться.

Мне кажется ты считаешь что revents это цельное числовое поле, которое надо проверять целиком. Нет, это не так. Смотри в нём только те флаги, которые тебе нужны. POLLOUT - значит в сокет можно что-то отправить. POLLIN/POLLHUP - значит можно что-то прочитать (во втором случае - прочитается 0 байт, признак EOF). POLLERR - можно посмотреть ошибку. Никак рассуждать на тему «почему POLLOUT и POLLHUP вместе» не следует, эти флаги никак друг с другом не связаны и сообщают о независимых признаках.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)

А покажите, пожалуйста, фрагмент кода, которому достаётся такое странное значение, и скопируйте из терминала с отладчиком всю информацию, которую в этот момент принимает и возвращает poll(): весь массив fds[nfds] и код возврата из самой poll().

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

куски по циклу если, то вначале

...
        if ((rc = poll(poll_table, poll_entry - poll_table, delay)) <= 0)
        {
            if (rc < 0 && ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR))
            {
                fprintf(stderr, "ERROR SERVER rtsp poll: %d %s\n", errno, strerror(errno));
                break;
            }
#if DEBUG > 5
            fprintf(stdout, "POLL %d %d\n", rc, delay);
#endif /* DEBUG > 5 */
            if (!pictx->isRun) continue;
        }
...

потом цикл в цикле по соединениями, отдельный казе куда приходит

...
                case RTSPSTATE_SEND_PACKET:
                    if (ctx->poll_entry->revents & (POLLERR | POLLHUP))
                    {
                        av_freep(&ctx->packet_buffer);
                        hr = -1;
                        int err = 0;
                        socklen_t lerr = sizeof(err);
                        if (getsockopt(poll_entry->fd, SOL_SOCKET, SO_ERROR, &err, &lerr) < 0)
                            fprintf(stderr, "\nERROR SERVER rtsp getsockopt: %d %s\n", errno, strerror(errno));
                        if (err != 0)
                            fprintf(stderr, "\nERROR SERVER rtsp socket: %d %s\n", err, strerror(err));
                    }
                    else if (ctx->poll_entry->revents & POLLOUT)
                    {
                        len = send(ctx->fd, ctx->packet_buffer_ptr, ctx->packet_buffer_end - ctx->packet_buffer_ptr, 0);
                        if (len < 0)
                        {
                            if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR))
                            {
                                av_freep(&ctx->packet_buffer);
                                hr = -1;
                            }
                            break;
                        }
                        ctx->packet_buffer_ptr += len;
                        if (ctx->packet_buffer_ptr >= ctx->packet_buffer_end)
                        {
                            av_freep(&ctx->packet_buffer);
                            ctx->state = RTSPSTATE_WAIT_REQUEST;
                        }
                    }
                    break;
...

выхлопы все чуть позже, как проверю что будет если убрать здесь проверку POLLHUP

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

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

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

да, почему может приходит POLLHUP и POLLOUT одновременно в целом понятно, как писали выше наверное выполняется shutdown чтобы закрыть сразу все rtsp/rtp/rtcp соединения связанные с контекстом.

осталось понять почему та сторона это делает )

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

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

wolverin ★★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария