lseek/write внезапно возвращается-1 с errno = 9 (Плохой дескриптор файла)

Мое использование приложения lseek() искать желаемое положение для записи данных. Файл успешно открыт с помощью open() и мое приложение смогло использовать lseek() и write() много времен.

В установленный срок, для некоторых пользователей и не легко восстанавливаемый, lseek() возвраты-1 с errno из 9. Файл не закрывается, прежде чем это и дескриптор файла (интервал) не сбрасываются.

После этого другой файл создается; open() хорошо снова и lseek() и write() работы снова.

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

Таким образом, мой вопрос, ОС может закрыть дескриптор файла для меня по некоторым причинам? Что могло вызвать это? Индексатор файла или какой-то сканер файла?

Что является лучшим способом решить это; действительно ли этот псевдо код является лучшим решением? (не берите в голову размещение кода, создаст функции для него),

int fd=open(...);
if (fd>-1) {
  long result = lseek(fd,....);
  if (result == -1 && errno==9) {
      close(fd..); //make sure we try to close nicely
      fd=open(...);

      result = lseek(fd,....);
  }
}

Кто-либо испытывает с чем-то подобным?

Сводка: файл ищет и пишет работы хорошо для данного fd, и внезапно отдает errno=9 без причины.

5
задан DevSolar 30 March 2010 в 12:23
поделиться

4 ответа

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

Если файл / устройство, которое вы открываете, реализовано как серверное приложение (например, NFS), подумайте, что может произойти, если серверное приложение выйдет из строя / перезапустится / перезагрузится. Дескриптор файла, хотя изначально действительный на стороне клиента, может больше не отображаться на действительный дескриптор файла на стороне сервера. Это, вероятно, может привести к последовательности событий, при которой клиент получит EBADF.

Надеюсь, это поможет.

1
ответ дан 13 December 2019 в 22:05
поделиться

Итак, мой вопрос в том, может ли ОС по какой-то причине закрыть ручку файла для меня? Что может вызвать > это? Какой-нибудь индексатор файлов или сканер файлов?

Нет, этого не произойдет.

Каков наилучший способ решить эту проблему; является ли этот псевдокод - лучшее решение? (не обращайте внимания на схему кода, буду создавать функции для этого)

Нет, лучший способ - найти ошибку и исправить ее.

Кто-нибудь сталкивался с чем-то подобным?

Я много раз видел, как fds путаются, приводя к EBADF в некоторых случаях, и эффектно взрываются в других, это были:

  • переполнения буфера - переполнение чего-то и запись бессмысленного значения в переменную 'int fd;'.
  • глупые ошибки, возникающие из-за того, что кто-то сделал какой-то угловой случай. if(fd = foo[i].fd), когда они имели в виду if(fd == foo[i].fd)
  • Противоречия между потоками, какой-то поток закрывает не тот дескриптор файла, который хочет использовать другой поток.

Если вы можете найти способ воспроизвести эту проблему, запустите свою программу под 'strace', чтобы увидеть, что происходит.

7
ответ дан 13 December 2019 в 22:05
поделиться

Нет, ОС не должна закрывать дескрипторы файлов просто так, и другие приложения (сканеры файлов и т. Д.) Не должны делать это.

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

  1. Проверьте свои предположения. Установлен ли errno в 0 перед вызовом? Действительно ли fd действителен в момент совершения вызова? (Я знаю, что вы сказали, что это так, но вы проверили это?)
  2. Каков результат put (strerror (9)); на вашей платформе?
0
ответ дан 13 December 2019 в 22:05
поделиться

ОС не должна случайным образом закрывать дескрипторы файлов (я предполагаю, что это Unix-подобная система). Если ваш дескриптор файла закрыт, значит, с вашим кодом что-то не так, скорее всего, где-то в другом месте (благодаря языку C и Unix API, это действительно может быть где угодно в коде и может быть связано, например, с небольшим буфером переполнение в каком-то фрагменте кода, который действительно выглядит не связанным).

Ваш псевдокод - наихудшее решение, так как он создаст впечатление, что проблема исправлена, а ошибка все еще скрывается.

Я предлагаю вам добавлять отладочные отпечатки (т.е. вызовы printf () ) везде, где вы открываете и закрываете файл или сокет. Также попробуйте Valgrind .

(У меня только вчера произошло жуткое переполнение буфера размером менее 1, которое повредило наименее значимый байт временного слота, созданного компилятором для сохранения регистра ЦП; косвенным эффектом было то, что структура в другой функции, по-видимому, быть сдвинутым на несколько байтов. Мне потребовалось некоторое время, чтобы понять, что происходит, включая некоторое тщательное чтение ассемблерного кода Mips).

2
ответ дан 13 December 2019 в 22:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: