LINUX.ORG.RU

level-triggered: продолжают приходить EPOLLIN после recv_bytes == 0 (EOF)

 


0

1

Продолжают приходить EPOLLIN после EAGAIN. Почему такое может происходить?

Схема кода:

 while(f_work) {
  // нам нужен бесконечный цикл ожидания (-1)
  int nfds = epoll_wait(epfd, events, MAX_EVENTS, EPOLL_RUN_TIMEOUT);
  if (nfds == -1) {
    perror("epoll_wait()");
  }
  else /* for */
  for (int i = 0; i < nfds; i++) {
    int fd = events[i].data.fd;
    if (fd == listener) {
      ...
      ev.events = EPOLLIN; // not EPOLLET
      ev.data.fd = s;
      if (epoll_ctl(epfd, EPOLL_CTL_ADD, s, &ev) == ENOSPC) {
        printf("Error: epoll_ctl(ADD,)\n");
        goto failure;
      }
    }
    else {
      // in level-triggered interface, for available data
      // an error has occured
      if ((events[i].events & EPOLLERR) ||
          (events[i].events & EPOLLHUP) ||
          (!(events[i].events & EPOLLIN))) {
        printf("epoll error\n");
        close(fd);
        continue;
      }
      uint8_t rdbuf[RDBUF_SIZE];
      ssize_t read_bytes = recv(fd, &rdbuf, RDBUF_SIZE, 0); // .. len, flags = 0
    }
  }
 }
видна ли здесь ошибка?

★★★★★

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

Я решил проблему указанием:

ev.events = 0;
ev.data.fd = fd;
if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == ENOSPC) {
printf(«Error: epoll_ctl(MOD,)\n»);
goto failure;
}
после errno == EAGAIN

Правильно ли это?

pacify ★★★★★
() автор топика

Чото я ничего не понял из этого куска. Где у тебя вычитывание то?

Вообще такое быть конечно может, но как бы не должно.

vasily_pupkin ★★★★★
()
Ответ на: комментарий от pacify
epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == ENOSPC

А я вообще не понял, зачем тут нужен EPOLL_CTL_MOD?

uint8_t rdbuf[RDBUF_SIZE];
      ssize_t read_bytes = recv(fd, &rdbuf, RDBUF_SIZE, 0); // .. len, flags = 0

Может лучше читать в цикле? Возможно будешь меньше гонять epoll_wait().

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

Вообще такое быть конечно может, но как бы не должно.

Поправка: epoll_wait() возвращает = 1 после того как recv() стал возвращать 0. Ошибка EAGAIN не появляется.
Попробую выкинуть всё лишнее из кода и выложить исходник примерно через час.

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

EOF же. Закрывай сокет

Я в сетевом программировании только начинаю разбираться.
Поэтому мне не понятно, зачем закрывать TCP-сокет, если я из него ещё буду ждать данные?
Или в этом случае как-то по-особому надо использовать epoll_wait()? (чтобы он не реагировал на EOF)

P.S. level-triggered режим сейчас заработал нормально, но смущает необходимость закрытия сокета.

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

Ты собираешься читать данные из закрытого сокета?

Сервер постоянно ждёт и принимает данные из клиентского сокета.
Клиент делает send(), потом ещё раз send() ...
Зачем серверу закрывать сокет, если данные ещё будут?
Мне нужно лишь, чтобы в случае EOF, на это не реагировал epoll_wait(), и не возвращал EPOLLIN.

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

данные из закрытого сокета?

всё, я тебя понял

я действительно делал sock.close() на клиентской стороне после sock.send()

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