Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 11:27
Оценка:
1) Непонятная проблема происходит при закрытии дескриптора файла (открытого файла на чтение) в коде на C++ ниже (ОС Linux). Это метод класса, который
вызывается периодически по таймеру. Если я вставляю в конце этой функции close(barcode_fd), то программа падает в segmentation fault, а если оставляю без оператора close, то программа работает правильно, но в системе со временем исчерпываются все дескрипторы файлов, что очевидно, т. к. они не закрываются в программе.

Буду благодарен, если кто подскажет почему close() не хочет закрывать дескриптор и как это сделать правильно?

(Наличие или отсутствие флага O_NONBLOCK никак не влияет на решение проблемы, т. е. все точно также как я описал, то же самое с любым текстовым файлом, не обязательно /dev/ttyACM0.)

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

int FromFtpForm::getBarcode()
{
    int barcode_fd;
    char buf_barcode[150];

    barcode_fd = open("/dev/ttyACM0", O_RDONLY| O_NONBLOCK);
    if (barcode_fd < 0) return -1;

   for (int i=0; i<150; i++) buf_barcode[i] = '\0';

    read(barcode_fd, buf_barcode, sizeof(buf_barcode));

    close(barcode_fd); // Если этот убрать, то программа работает, если оставить, то падает

    return 0;
}
Re: Непонятная ошибка при закрытии дескриптора файла
От: CaptainFlint http://flint-inc.ru/
Дата: 28.09.14 12:12
Оценка:
Здравствуйте, skl, Вы писали:

skl>1) Непонятная проблема происходит при закрытии дескриптора файла (открытого файла на чтение) в коде на C++ ниже (ОС Linux). Это метод класса, который

skl>вызывается периодически по таймеру. Если я вставляю в конце этой функции close(barcode_fd), то программа падает в segmentation fault, а если оставляю без оператора close, то программа работает правильно, но в системе со временем исчерпываются все дескрипторы файлов, что очевидно, т. к. они не закрываются в программе.

Странное что-то. Может, где-то в другом месте рушится стек или куча, а close всего лишь случайным образом оказался триггером? Падение происходит в самом close() или где-то дальше по коду? Если дальше, то что возвращает close()? (И read() заодно уж.)
А если временно переписать на fopen/fread/fclose, проблема останется?
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re: Непонятная ошибка при закрытии дескриптора файла
От: Zhendos  
Дата: 28.09.14 13:22
Оценка:
Здравствуйте, skl, Вы писали:

skl>1) Непонятная проблема происходит при закрытии дескриптора файла (открытого файла на чтение) в коде на C++ ниже (ОС Linux). Это метод класса, который

skl>вызывается периодически по таймеру. Если я вставляю в конце этой функции close(barcode_fd), то программа падает в segmentation fault, а если оставляю без оператора close, то программа работает правильно, но в системе со временем исчерпываются все дескрипторы файлов, что очевидно, т. к. они не закрываются в программе.


skl>
skl>int FromFtpForm::getBarcode()
skl>{
skl>    int barcode_fd;
skl>    char buf_barcode[150];

skl>    barcode_fd = open("/dev/ttyACM0", O_RDONLY| O_NONBLOCK);
skl>    if (barcode_fd < 0) return -1;

skl>   for (int i=0; i<150; i++) buf_barcode[i] = '\0';

skl>    read(barcode_fd, buf_barcode, sizeof(buf_barcode));

skl>    close(barcode_fd); // Если этот убрать, то программа работает, если оставить, то падает

skl>    return 0;
skl>}
skl>


ИМХО ошибка не в приведенном коде, а где-то еще.
Используйте valgrind или gcc + "-fsanitize=address"
Re[2]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 13:31
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>Здравствуйте, skl, Вы писали:


skl>>1) Непонятная проблема происходит при закрытии дескриптора файла (открытого файла на чтение) в коде на C++ ниже (ОС Linux). Это метод класса, который

skl>>вызывается периодически по таймеру. Если я вставляю в конце этой функции close(barcode_fd), то программа падает в segmentation fault, а если оставляю без оператора close, то программа работает правильно, но в системе со временем исчерпываются все дескрипторы файлов, что очевидно, т. к. они не закрываются в программе.

CF>Странное что-то. Может, где-то в другом месте рушится стек или куча, а close всего лишь случайным образом оказался триггером? Падение происходит в самом close() или где-то дальше по коду? Если дальше, то что возвращает close()? (И read() заодно уж.)

CF>А если временно переписать на fopen/fread/fclose, проблема останется?

Я пробовал временно переписывать с помощью стандартных файловых потоков C++ (ifstream) — все работает без ошибок close в этом случае закрывает без проблем, но чтение блокируемое становится, как его сделать неблокируемым на С++, т. е. как установить O_NONBLOCK я не знаю.
Re[2]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 13:45
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>ИМХО ошибка не в приведенном коде, а где-то еще.

Z>Используйте valgrind или gcc + "-fsanitize=address"

Это практически невозможно сделать, т. к. я кросскомпилирую (на x86 компьютере) свой код специальным arm-gcc компилятором (для arm9 машины). Выполнить код и посмотреть его работу я могу только на том устройстве для которого кросскомпилирую код (установить туда какие-то средства отладки практически невозможное дело, использую просто отладочные вывод с помощью printf в консоль).
Код довольно-таки обширный и проблем я никаких не знал до сих пор, так что на кросскомпилятор не хочу грешить.
Re[3]: Непонятная ошибка при закрытии дескриптора файла
От: Zhendos  
Дата: 28.09.14 14:10
Оценка:
Здравствуйте, skl, Вы писали:

skl>Здравствуйте, Zhendos, Вы писали:


Z>>ИМХО ошибка не в приведенном коде, а где-то еще.

Z>>Используйте valgrind или gcc + "-fsanitize=address"

skl>Это практически невозможно сделать, т. к. я кросскомпилирую (на x86 компьютере) свой код специальным arm-gcc компилятором (для arm9 машины). Выполнить код и посмотреть его работу я могу только на том устройстве для которого кросскомпилирую код (установить туда какие-то средства отладки практически невозможное дело, использую просто отладочные вывод с помощью printf в консоль).

skl>Код довольно-таки обширный и проблем я никаких не знал до сих пор, так что на кросскомпилятор не хочу грешить.

Я тоже в свое время разрабатывал для linux/arm9.
1)Работу с компортом можно эмулировать на x86 с помощью openpty,
и ваш код прогнать на обычном PC
2)core dump, запускаете "ulimit -c unlimitted" на "железке", забираете "core*" файл с железки
и потом на PC с помощью gdb из toolchain разбираетесь

когда мне не помогали 1 и 2
3)я кросс компилировал и поставил gdb на железку

и кстати valgrind и -fsanitize=address портированы на arm.

PS
а на компилятор я бы не стал грешить, скорее на ваш "обширный" код.
Re: Непонятная ошибка при закрытии дескриптора файла
От: c-smile Канада http://terrainformatica.com
Дата: 28.09.14 14:25
Оценка:
Здравствуйте, skl, Вы писали:

skl>2) Я понимаю, что это скорее сишный код в методе, но я не знаю как с помощью файловых потоков С++ задать неблокируемый режим для файла на чтение (т. е. флаг O_NONBLOCK). Буду благодарен за подсказку как это сделать при помощи файловых потоков С++.


Ты зовешь read() и не дожидаясь его завершения — close() и более того разрушаешь буффер. понятно что упадет где-нибудь.

Мне кажется тв не понимаешь как работатет O_NONBLOCK — т.е. не блокирующий IO

http://www.kegel.com/dkftpbench/nonblocking.html
Re[4]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 14:28
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Я тоже в свое время разрабатывал для linux/arm9.

Z>1)Работу с компортом можно эмулировать на x86 с помощью openpty,
Z>и ваш код прогнать на обычном PC
Z>2)core dump, запускаете "ulimit -c unlimitted" на "железке", забираете "core*" файл с железки
Z>и потом на PC с помощью gdb из toolchain разбираетесь

Z>когда мне не помогали 1 и 2

Z>3)я кросс компилировал и поставил gdb на железку

Z>и кстати valgrind и -fsanitize=address портированы на arm.


Z>PS

Z>а на компилятор я бы не стал грешить, скорее на ваш "обширный" код.

Спасибо за подсказки.
Re[2]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 14:33
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, skl, Вы писали:


skl>>2) Я понимаю, что это скорее сишный код в методе, но я не знаю как с помощью файловых потоков С++ задать неблокируемый режим для файла на чтение (т. е. флаг O_NONBLOCK). Буду благодарен за подсказку как это сделать при помощи файловых потоков С++.


CS>Ты зовешь read() и не дожидаясь его завершения — close() и более того разрушаешь буффер. понятно что упадет где-нибудь.


CS>Мне кажется тв не понимаешь как работатет O_NONBLOCK — т.е. не блокирующий IO


CS>http://www.kegel.com/dkftpbench/nonblocking.html



Может быть не понимаю, спасибо почитаю по ссылке.

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

Это выносил из функ-ции в privite класса:

int barcode_fd;
char buf_barcode[150];

Результат тот же был — падение на close.
Re[2]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 14:48
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, skl, Вы писали:


skl>>2) Я понимаю, что это скорее сишный код в методе, но я не знаю как с помощью файловых потоков С++ задать неблокируемый режим для файла на чтение (т. е. флаг O_NONBLOCK). Буду благодарен за подсказку как это сделать при помощи файловых потоков С++.


CS>Ты зовешь read() и не дожидаясь его завершения — close() и более того разрушаешь буффер. понятно что упадет где-нибудь.


CS>Мне кажется тв не понимаешь как работатет O_NONBLOCK — т.е. не блокирующий IO


CS>http://www.kegel.com/dkftpbench/nonblocking.html



И как я написал в первом посте наличие или отсутствие O_NONBLOCK в коде никак не влияет на решение проблемы, падает и с этим флагом и без него. Не падает только если open/read не использовать, а их аналоги из C++.
Re[2]: Непонятная ошибка при закрытии дескриптора файла
От: Zhendos  
Дата: 28.09.14 15:34
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, skl, Вы писали:


skl>>2) Я понимаю, что это скорее сишный код в методе, но я не знаю как с помощью файловых потоков С++ задать неблокируемый режим для файла на чтение (т. е. флаг O_NONBLOCK). Буду благодарен за подсказку как это сделать при помощи файловых потоков С++.


CS>Ты зовешь read() и не дожидаясь его завершения — close() и более того разрушаешь буффер. понятно что упадет где-нибудь.


CS>Мне кажется тв не понимаешь как работатет O_NONBLOCK — т.е. не блокирующий IO


CS>http://www.kegel.com/dkftpbench/nonblocking.html



Вы точно в этом уверены? неблокирующий read, это не async, указатель никуда не копируется
и в фоне никакие IO операции не производятся.

Он(read) просто скопирует в буфер то, что есть в буфере ОС и отдаст управление,
после этого с буфером можно делать что угодно. И файл можно без проблем закрыть.

PS
Хотя код конечно странно выглядит, взять хотя бы ручную реализацию std::fill/memset
перед read.
Re[3]: Непонятная ошибка при закрытии дескриптора файла
От: Ops Россия  
Дата: 28.09.14 15:57
Оценка:
Здравствуйте, skl, Вы писали:

skl>Это практически невозможно сделать, т. к. я кросскомпилирую (на x86 компьютере) свой код специальным arm-gcc компилятором (для arm9 машины). Выполнить код и посмотреть его работу я могу только на том устройстве для которого кросскомпилирую код (установить туда какие-то средства отладки практически невозможное дело, использую просто отладочные вывод с помощью printf в консоль).

JTAG
skl>Код довольно-таки обширный и проблем я никаких не знал до сих пор, так что на кросскомпилятор не хочу грешить.
Не греши, собирай в виртуалке.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[3]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 16:07
Оценка:
Здравствуйте, Zhendos, Вы писали:


Z>Вы точно в этом уверены? неблокирующий read, это не async, указатель никуда не копируется

Z>и в фоне никакие IO операции не производятся.

Z>Он(read) просто скопирует в буфер то, что есть в буфере ОС и отдаст управление,

Z>после этого с буфером можно делать что угодно. И файл можно без проблем закрыть.

Z>PS

Z>Хотя код конечно странно выглядит, взять хотя бы ручную реализацию std::fill/memset
Z>перед read.

Про NONBLOCK — уверен. Я даже пробовал не читать, а писать (фук-ей write) в обычный текстовый файл (открытый без всяких NONBLOCK) и после этого закрывать файл и тоже падает на close().

Про std::memset — конечно лучше. В данном коде я просто вручную забил нулями буфер через for чтобы быть уверенным что дело в не в memset().
Re[4]: Непонятная ошибка при закрытии дескриптора файла
От: Zhendos  
Дата: 28.09.14 16:19
Оценка:
Здравствуйте, skl, Вы писали:

skl>Здравствуйте, Zhendos, Вы писали:



skl>Про std::memset — конечно лучше. В данном коде я просто вручную забил нулями буфер через for чтобы быть уверенным что дело в не в memset().


Не, я имел ввиду, что странно не только не использование memset, но и использование его замены.
Ведь read запишет сколько сможет и вернет количество записанных байт, так что
этот код выглядит как:
int i;
i = 10;//(1)
i = 15;


(1) конечно не повредит, но и смысла в нем никакого.
Re[5]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 16:37
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Здравствуйте, skl, Вы писали:


skl>>Здравствуйте, Zhendos, Вы писали:



skl>>Про std::memset — конечно лучше. В данном коде я просто вручную забил нулями буфер через for чтобы быть уверенным что дело в не в memset().


Z>Не, я имел ввиду, что странно не только не использование memset, но и использование его замены.

Z>Ведь read запишет сколько сможет и вернет количество записанных байт, так что
Z>этот код выглядит как:
Z>
Z>int i;
Z>i = 10;//(1)
Z>i = 15;
Z>


Z>(1) конечно не повредит, но и смысла в нем никакого.



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

char buf_barcode[150] = { 0 };

Но это к теме не относится.
Re[6]: Непонятная ошибка при закрытии дескриптора файла
От: Zhendos  
Дата: 28.09.14 17:02
Оценка: +1
Здравствуйте, skl, Вы писали:


skl>Но с буфером-то я произвожу после чтения кое-какие манипуляции (этот код убран мной в форуме) и мне желательно чтобы строка нулем заканчивалась, и я не уверен что после чтения read в строке будет нуль в конце, поэтому и забиваю нулями буфер заранее.

skl>Вообще в данном случае наверное лучше инициализировать так:

skl>char buf_barcode[150] = { 0 };


skl>Но это к теме не относится.


В таком случае правильнее делать так
char buf[150];
const ssize_t n = read(fd, buf, sizeof(buf) - 1); 
if (n < 0) {
//handle errors
}
buf[n] = '\0';


зачем занулять, 150 байт, если нужно занулить 1.
Отредактировано 28.09.2014 17:25 Zhendos . Предыдущая версия .
Re[5]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 17:05
Оценка:
Это кстати USB: /dev/ttyACM0.

Чтобы было понятно в коде я хочу периодически делать чтение этого файла на предмет появления новых данных, которые читаю и вывожу в окно (QT), естественно я не хочу чтобы на чтении этого файла блокировалась вся программа, поэтому указываю NONBLOCK. Отдельный поток не очень хочется отводить. Не работает именно с линуксовыми функциями open/read (без разницы NONBLOCK или без NONBLOCK), а с функциями c++ для работы с файлами программа не падает, но не понятно как nonblock указать.
Re[6]: Непонятная ошибка при закрытии дескриптора файла
От: Zhendos  
Дата: 28.09.14 17:24
Оценка:
Здравствуйте, skl, Вы писали:



skl>Это кстати USB: /dev/ttyACM0.


skl>Чтобы было понятно в коде я хочу периодически делать чтение этого файла на предмет появления новых данных, которые читаю и вывожу в окно (QT), естественно я не хочу чтобы на чтении этого файла блокировалась вся программа, поэтому указываю NONBLOCK. Отдельный поток не очень хочется отводить.


Если не хочется поток новый создавать (я бы создал),
то можно использовать QSocketNotifier, и не переоткрывать файл переодически,
а открыть один раз.
Re[7]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 28.09.14 17:44
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Здравствуйте, skl, Вы писали:




skl>>Это кстати USB: /dev/ttyACM0.


skl>>Чтобы было понятно в коде я хочу периодически делать чтение этого файла на предмет появления новых данных, которые читаю и вывожу в окно (QT), естественно я не хочу чтобы на чтении этого файла блокировалась вся программа, поэтому указываю NONBLOCK. Отдельный поток не очень хочется отводить.


Z>Если не хочется поток новый создавать (я бы создал),

Z>то можно использовать QSocketNotifier, и не переоткрывать файл переодически,
Z>а открыть один раз.

Не уверен что QSocketNotifier есть в QT2 (не использую QT4-5 т. к. медленно работает на моем устройстве). Но упоминание про QT навело меня сейчас на мысль, что QT создает свои потоки (для своих нужд) и соответственно мой код может работать в нескольких потоках созданных этой библиотекой. Закрытие close() в одном из них естественно вызывает сбой, т. к. тот же файл открыт в других ее потоках. Попробую завтра этот код поместить в отдельный Singelton и напишу если получится.
Re[6]: Непонятная ошибка при закрытии дескриптора файла
От: VVV Россия  
Дата: 28.09.14 23:00
Оценка:
Здравствуйте, skl, Вы писали:

skl>Но с буфером-то я произвожу после чтения кое-какие манипуляции (этот код убран мной в форуме) и мне желательно чтобы строка нулем заканчивалась, и я не уверен что после чтения read в строке будет нуль в конце, поэтому и забиваю нулями буфер заранее.


Похоже, что выходите за пределы массива при 'манипуляциях' и затираете переменную int barcode_fd;. printf("%d\n", barcode_fd) после open и printf перед close могут помочь в поиске ошибки.
Re[2]: Непонятная ошибка при закрытии дескриптора файла
От: ononim  
Дата: 29.09.14 00:49
Оценка:
skl>>2) Я понимаю, что это скорее сишный код в методе, но я не знаю как с помощью файловых потоков С++ задать неблокируемый режим для файла на чтение (т. е. флаг O_NONBLOCK). Буду благодарен за подсказку как это сделать при помощи файловых потоков С++.
CS>Ты зовешь read() и не дожидаясь его завершения — close() и более того разрушаешь буффер. понятно что упадет где-нибудь.
CS>Мне кажется тв не понимаешь как работатет O_NONBLOCK — т.е. не блокирующий IO
это юникс, тут все не так)
виндовс-стайл асинк-IO тут делается через это или это
Как много веселых ребят, и все делают велосипед...
Re: Непонятная ошибка при закрытии дескриптора файла
От: ononim  
Дата: 29.09.14 00:52
Оценка: +1
skl>
skl>int FromFtpForm::getBarcode()
skl>{
skl>    int barcode_fd;
skl>    char buf_barcode[150];

skl>    barcode_fd = open("/dev/ttyACM0", O_RDONLY| O_NONBLOCK);
skl>    if (barcode_fd < 0) return -1;

skl>   for (int i=0; i<150; i++) buf_barcode[i] = '\0';

skl>    read(barcode_fd, buf_barcode, sizeof(buf_barcode));

skl>    close(barcode_fd); // Если этот убрать, то программа работает, если оставить, то падает

skl>    return 0;
skl>}
skl>


Это не минимальный падающий код. Минимальный выглядел бы так:
int main() //<-- ВСЯ РАЗНИЦА ТУТ;)
{
    int barcode_fd;
    char buf_barcode[150];

    barcode_fd = open("/dev/ttyACM0", O_RDONLY| O_NONBLOCK);
    if (barcode_fd < 0) return -1;

    for (int i=0; i<150; i++) buf_barcode[i] = '\0';

    read(barcode_fd, buf_barcode, sizeof(buf_barcode));
    close(barcode_fd); // Если этот убрать, то программа работает, если оставить, то падает

    return 0;
}

..но он не падает. так что ищите баги в других местах
Как много веселых ребят, и все делают велосипед...
Re[2]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 29.09.14 04:11
Оценка:
Как я и предполагал поместил приведенную мной функцию в отдельный Singelton и код заработал без проблем, т. е. в Singelton'е open/read/close делается без всяких проблем. Очевидно библиотека QT вмешивалась в работу кода, как я и предположил немного ранее.

Всем спасибо, нужно было с кем-то умными поговорить чтобы навели на мысль и мысль пришла. Всем пока!
Re[3]: Непонятная ошибка при закрытии дескриптора файла
От: ononim  
Дата: 29.09.14 08:35
Оценка: +4 :)
skl>Как я и предполагал поместил приведенную мной функцию в отдельный Singelton и код заработал без проблем, т. е. в Singelton'е open/read/close делается без всяких проблем. Очевидно библиотека QT вмешивалась в работу кода, как я и предположил немного ранее.
skl>Всем спасибо, нужно было с кем-то умными поговорить чтобы навели на мысль и мысль пришла. Всем пока!
То есть баг вы не пофиксили, а написали код так, чтоб он перестал воспроизводиться. Ничего, вылезет когда нибудь. Перед релизом скорее всего.
Как много веселых ребят, и все делают велосипед...
Re[3]: Непонятная ошибка при закрытии дескриптора файла
От: Кодт Россия  
Дата: 29.09.14 09:32
Оценка:
Здравствуйте, skl, Вы писали:

skl>Как я и предполагал поместил приведенную мной функцию в отдельный Singelton и код заработал без проблем, т. е. в Singelton'е open/read/close делается без всяких проблем. Очевидно библиотека QT вмешивалась в работу кода, как я и предположил немного ранее.


Если завёртывание в однопоточный апартамент спасло, это наводит на мысли, что должен падать код вида
int f1 = open(same_filename, O_RDONLY|O_NONBLOCK);
int f2 = open(same_filename, O_RDONLY|O_NONBLOCK);

read(f1, buf1, size);
read(f2, buf2, size);

close(f1);
close(f2);

То есть, или использование файла вообще нереентерабельно (любого файла, или конкретно /dev/ttyACM0), или нереентерабельно гоночное открытие, чтение или закрытие
#omp parallel for
for(int i=0; i<2; ++i)
  f[i] = open(same_file, O_RDONLY|O_NONBLOCK);

#omp parallel for
for(int i=0; i<2; ++i)
  read(f[i], buf[i], size);

#omp parallel for
for(int i=0; i<2; ++i)
  close(f[i]);


Если дело обстоит именно так, то выход — обернуть в критическую секцию любой степени изоляционизма (хоть в синглетон, хоть ещё как).
Но здесь нужно учитывать такую штуку, как инверсия приоритетов и неявные дедлоки. То есть, если процедура открытия или чтения затянется по причине внешней блокировки устройства, его неготовности или тормозливости, то твой вызывающий поток заснёт на неопределённое время. Насколько это место критично?
Например, вызывая потенциально тормозливую функцию из GUI, можно заморозить экран.
Перекуём баги на фичи!
Re[3]: Непонятная ошибка при закрытии дескриптора файла
От: smeeld  
Дата: 29.09.14 09:35
Оценка:
Здравствуйте, ononim, Вы писали:


CS>>Мне кажется тв не понимаешь как работатет O_NONBLOCK — т.е. не блокирующий IO

O>это юникс, тут все не так

Да, в линуксах, например, O_NONBLOCK есть флаг в поле структуры file, которая
ассоциируется с любым IO дескриптором и установка которого проверяется при
невозможности чтения/записи в дескриптор, если флаг не установлен, засыпаем,
в противном случае, возвращаем -EAGAIN
На примерах из linux:

 if (sock->file->f_flags & O_NONBLOCK)
                 flags |= MSG_DONTWAIT;
         err = sock_recvmsg(sock, &msg, size, flags);
....................................................................................

 err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,
                                    flags & ~MSG_DONTWAIT, &addr_len);
....................................................................................

if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) &&
             (sk->sk_state == TCP_ESTABLISHED))
                 sk_busy_loop(sk, nonblock);
 lock_sock(sk);
 
         err = -ENOTCONN;
         if (sk->sk_state == TCP_LISTEN)
                 goto out;
 
         timeo = sock_rcvtimeo(sk, nonblock);
......................................................................................

 if (signal_pending(current)) {
                                 copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
                                break;
.......................................................................................

      release_sock(sk);
         return copied;


В случае с драйвером и дескриптором ttyACM так:

 if (!input_available_p(tty, 0)) {
                         if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
                                 up_read(&tty->termios_rwsem);
                                 tty_flush_to_ldisc(tty);
                                 down_read(&tty->termios_rwsem);
                                 if (!input_available_p(tty, 0)) {
                                         retval = -EIO;
                                         break;
                                 }
                         } else {
                                 if (tty_hung_up_p(file))
                                         break;
                                 if (!timeout)
                                         break;
                                if (file->f_flags & O_NONBLOCK) {
                                        retval = -EAGAIN;
                                         break;
                                 }
                                 if (signal_pending(current)) {
                                         retval = -ERESTARTSYS;
                                         break;
                                 }
Re: Непонятная ошибка при закрытии дескриптора файла
От: zaufi Земля  
Дата: 29.09.14 12:57
Оценка:
Здравствуйте, skl, Вы писали:

skl>2) Я понимаю, что это скорее сишный код в методе, но я не знаю как с помощью файловых потоков С++ задать неблокируемый режим для файла на чтение (т. е. флаг O_NONBLOCK). Буду благодарен за подсказку как это сделать при помощи файловых потоков С++.


использовать std::istream::readsome() вместо read()
Re[2]: Непонятная ошибка при закрытии дескриптора файла
От: ononim  
Дата: 29.09.14 13:10
Оценка: +1
skl>>2) Я понимаю, что это скорее сишный код в методе, но я не знаю как с помощью файловых потоков С++ задать неблокируемый режим для файла на чтение (т. е. флаг O_NONBLOCK). Буду благодарен за подсказку как это сделать при помощи файловых потоков С++.
Z>использовать std::istream::readsome() вместо read()
Да блин у человека явно какой то баг в окружающем коде. Его надо фиксить. Я кстати процентов на 60 уверен что close у него не тот, который он хочет позвать — макросом переопределили каким то или гдето в проекте есть другой левый close, на который и слинковался код. Вобщем, gdb в зубы и вперед.
Как много веселых ребят, и все делают велосипед...
Отредактировано 29.09.2014 13:28 ononim . Предыдущая версия .
Re[3]: Непонятная ошибка при закрытии дескриптора файла
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.09.14 14:10
Оценка:
Здравствуйте, skl, Вы писали:

skl>Это практически невозможно сделать, т. к. я кросскомпилирую (на x86 компьютере) свой код специальным arm-gcc компилятором (для arm9 машины). Выполнить код и посмотреть его работу я могу только на том устройстве для которого кросскомпилирую код (установить туда какие-то средства отладки практически невозможное дело, использую просто отладочные вывод с помощью printf в консоль).

skl>Код довольно-таки обширный и проблем я никаких не знал до сих пор, так что на кросскомпилятор не хочу грешить.

На том устройстве можно получить core dump от программы? Если да, получите его, перетащите на PC, соберите (или найдите) cross-gdb и посмотрите, где оно падает.
Re[2]: Непонятная ошибка при закрытии дескриптора файла
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.09.14 14:13
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Ты зовешь read() и не дожидаясь его завершения — close() и более того разрушаешь буффер. понятно что упадет где-нибудь.


Это не венда с overlapped I/O, это линух. read(), как только вернулся, от буфера уже отсосался, и больше в него не полезет.
Re[7]: Непонятная ошибка при закрытии дескриптора файла
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.09.14 14:18
Оценка:
Здравствуйте, VVV, Вы писали:

VVV>Похоже, что выходите за пределы массива при 'манипуляциях' и затираете переменную int barcode_fd;. printf("%d\n", barcode_fd) после open и printf перед close могут помочь в поиске ошибки.


Не похоже. close() сам по себе не сигфолтится, даже если ему фуфло вместо дескриптора файла подсунуть.

Худшее, что может быть от передачи close() в качестве параметра мусора — это то, что он закроет какой-нибудь другой, не имеющий отношения к делу, файл (со случайно совпавшим номером). Что может сломать какой-то другой код, который работал с тем дескриптором. Но это какое-то уж слишком маловероятное стечение обстоятельств, IMHO.
Re[3]: Непонятная ошибка при закрытии дескриптора файла
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.09.14 14:21
Оценка: +1
Здравствуйте, skl, Вы писали:

skl>Всем спасибо, нужно было с кем-то умными поговорить чтобы навели на мысль и мысль пришла. Всем пока!


Это неправильная мысль. Очевидно, что падал не этот кусок кода (там нечему падать), а какой-то другой. Переорганизовав программу, вы спрятали проблему, а не решили ее. Когда-нибудь она опять вылезет. Причем, может вылезти в еще более непонятном виде. Лучше бы разобраться, пока у вас проблема, по крайней мере, воспроизводится устойчиво, чем прятать ее.
Re[4]: Непонятная ошибка при закрытии дескриптора файла
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.09.14 14:22
Оценка:
Здравствуйте, Кодт, Вы писали:

К>То есть, или использование файла вообще нереентерабельно (любого файла, или конкретно /dev/ttyACM0), или нереентерабельно гоночное открытие, чтение или закрытие

. . .
К>Если дело обстоит именно так, то выход — обернуть в критическую секцию любой степени изоляционизма (хоть в синглетон, хоть ещё как).

Дело не обстоит именно так. Линух не настолько плох
Re[4]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 29.09.14 15:01
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, skl, Вы писали:


skl>>Всем спасибо, нужно было с кем-то умными поговорить чтобы навели на мысль и мысль пришла. Всем пока!


Pzz>Это неправильная мысль. Очевидно, что падал не этот кусок кода (там нечему падать), а какой-то другой. Переорганизовав программу, вы спрятали проблему, а не решили ее. Когда-нибудь она опять вылезет. Причем, может вылезти в еще более непонятном виде. Лучше бы разобраться, пока у вас проблема, по крайней мере, воспроизводится устойчиво, чем прятать ее.



Я пишу с использованием QT2, вот такой код например работает чудесно, в том числе нет проблем закрытием:

QFile f("/dev/ttyACM0");
if ( f.open(IO_ReadOnly) )
{
QTextStream t( &f );

barcode = t.readLine();

f.close();
}

Но стоит использовать линуксовые функции open/read/close (не важно блокируемые или нет), то начинаются проблемы, почему-то именно падает на close().

Поэтому подозреваю, что проблема именно в QT и искать обходные пути в этом случае на мой взгляд правильно. Кстати, это не первая проблема именно с QT в процессе написания программы, например у меня не получилось заставить работать QT-классы для работы с FTP, естественно решил обходным путем — просто задействовал консольную ftp и с помощью нее сделал что требуется, и т. п. Это просто очередная заморочка с устаревшей версией QT, кстати linux тоже старенький 2.6 ядро. Использую старое потому что оно быстрее и меньше жрет ресурсов, что немаловажно для моего устройства.
Re[5]: Непонятная ошибка при закрытии дескриптора файла
От: ononim  
Дата: 29.09.14 15:02
Оценка:
skl>Но стоит использовать линуксовые функции open/read/close (не важно блокируемые или нет), то начинаются проблемы, почему-то именно падает на close().
а если писать не close(fd) а ::close(fd)?
Как много веселых ребят, и все делают велосипед...
Re[5]: Непонятная ошибка при закрытии дескриптора файла
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.09.14 15:39
Оценка:
Здравствуйте, skl, Вы писали:

skl>Но стоит использовать линуксовые функции open/read/close (не важно блокируемые или нет), то начинаются проблемы, почему-то именно падает на close().


Это наведенка. В close() нечему упасть. Даже если передать ему невалидные аргументы, он не упадет, а вернет ошибку.

Кстати, не факт, что там вызывается тот самый close(). В классе или его родителях нет метода close() с подходящими типами аргументов?

skl>Поэтому подозреваю, что проблема именно в QT и искать обходные пути в этом случае на мой взгляд правильно.


Если ситуация такова, что при использовании Qt работает, а без использования — нет, то вряд ли проблема в Qt. Вы же не думаете, что Qt за вами тайно следит, и наказывает за неиспользование себя сигфолтами?

skl>Кстати, это не первая проблема именно с QT в процессе написания программы, например у меня не получилось заставить работать QT-классы для работы с FTP, естественно решил обходным путем — просто задействовал консольную ftp и с помощью нее сделал что требуется, и т. п. Это просто очередная заморочка с устаревшей версией QT, кстати linux тоже старенький 2.6 ядро. Использую старое потому что оно быстрее и меньше жрет ресурсов, что немаловажно для моего устройства.


Когда я начинал работать с линухом, то ядро 1.2.13 было самым свежачком, вчера вышедшим, а Qt, по-моему, еще в природе не существовал. Так что стареньким меня не удивишь
Re[6]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 29.09.14 16:21
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Это наведенка. В close() нечему упасть. Даже если передать ему невалидные аргументы, он не упадет, а вернет ошибку.


Pzz>Кстати, не факт, что там вызывается тот самый close(). В классе или его родителях нет метода close() с подходящими типами аргументов?


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

В man вообще про close() следующее сообщается: "It is probably unwise to close file descriptors while they may be in use by system calls in other threads in the same process. Since a file descriptor may be re-used, there are some obscure race conditions that may cause unintended side effects. "

Я сам потоки в своей программе не создаю вообще.


Pzz>Если ситуация такова, что при использовании Qt работает, а без использования — нет, то вряд ли проблема в Qt. Вы же не думаете, что Qt за вами тайно следит, и наказывает за неиспользование себя сигфолтами?


И что конкретно вы предлагаете?


Pzz>Когда я начинал работать с линухом, то ядро 1.2.13 было самым свежачком, вчера вышедшим, а Qt, по-моему, еще в природе не существовал. Так что стареньким меня не удивишь


Вы, наверное, еще и emacs'ом пользуетесь и наверняка еще и vim.
Re[7]: Непонятная ошибка при закрытии дескриптора файла
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.09.14 16:54
Оценка:
Здравствуйте, skl, Вы писали:

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


Когда у вас отсутствует close(), то вместо него мало чего другого присутствует. Например, выделение/освобождение памяти. Если у вас где-то в другом месте присутствует "удар по памяти", то из-за этих добавленных операций с памятью он может приходиться на другое место, и не приводить к сигфолту.

Еще раз повторю, сам по себе close() не при чем. Ищите проблему в другом месте.

Pzz>>Если ситуация такова, что при использовании Qt работает, а без использования — нет, то вряд ли проблема в Qt. Вы же не думаете, что Qt за вами тайно следит, и наказывает за неиспользование себя сигфолтами?


skl>И что конкретно вы предлагаете?


Понять, где конкретно падает. Например, с помощью core dump'а.

Pzz>>Когда я начинал работать с линухом, то ядро 1.2.13 было самым свежачком, вчера вышедшим, а Qt, по-моему, еще в природе не существовал. Так что стареньким меня не удивишь


skl>Вы, наверное, еще и emacs'ом пользуетесь и наверняка еще и vim.


При чем тут?
Re[7]: Непонятная ошибка при закрытии дескриптора файла
От: ononim  
Дата: 29.09.14 16:55
Оценка:
skl>Я не говорю, что close() падает, а когда присутствует close() в моей функции то программа падает, а без close() работает, но при этом все дескрипторы в системе со временем исчерпывает (т. к. функция по таймеру запускается много раз).
skl>В man вообще про close() следующее сообщается: "It is probably unwise to close file descriptors while they may be in use by system calls in other threads in the same process. Since a file descriptor may be re-used, there are some obscure race conditions that may cause unintended side effects. "

Подумайте кстати над тем вопросом что случится, если ваш /dev/ttyACM0 внезапно от системы отвалится физически, а потом опять вернется
Как много веселых ребят, и все делают велосипед...
Re[8]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 30.09.14 04:10
Оценка:
Здравствуйте, ononim, Вы писали:

O>Подумайте кстати над тем вопросом что случится, если ваш /dev/ttyACM0 внезапно от системы отвалится физически, а потом опять вернется


В этом смысл каждый раз открытия и закрытия дескриптора. Иначе можно было бы где-нибудь в начале программы открыть один раз дескриптор и постоянно читать из него, но нет гарантии что в это время не вытащат и снова не вставят кабель.
Re[8]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 30.09.14 04:13
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Понять, где конкретно падает. Например, с помощью core dump'а.


Была бы core, то может быть.
Re[6]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 30.09.14 04:18
Оценка: :)
Здравствуйте, ononim, Вы писали:

skl>>Но стоит использовать линуксовые функции open/read/close (не важно блокируемые или нет), то начинаются проблемы, почему-то именно падает на close().

O>а если писать не close(fd) а ::close(fd)?

Этот способ с ::close(fd) заработал, т. е. в segmentation не падает и дескрипторы вроде в системе не исчерпываются.
Не понял только я в чем тут суть?

Однако при этом в буфер после чтения почему-то ничего не попадает, т. е. одни нули.

Я пробовал также делать и ::open() и ::read(), но все равно в буфере нули.

А если же при этом способе убрать флаг NONBLOCK, то нормально буфер заполняется принятыми данными, но read естественно становится блокируемым.

Что еще можете предложить?
Re[9]: Непонятная ошибка при закрытии дескриптора файла
От: Pzz Россия https://github.com/alexpevzner
Дата: 30.09.14 05:41
Оценка:
Здравствуйте, skl, Вы писали:

Pzz>>Понять, где конкретно падает. Например, с помощью core dump'а.


skl>Была бы core, то может быть.


ulimit -c unlimited
Re[10]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 30.09.14 06:52
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, skl, Вы писали:


Pzz>>>Понять, где конкретно падает. Например, с помощью core dump'а.


skl>>Была бы core, то может быть.


Pzz>ulimit -c unlimited


Нет core с этой командой и без нее. Даже "find / -name *core*" по всей системе делал после segmentation failure — нету core нигде. Это надо где-то в настройках искать непонятно где, может быть ядро перекомпилировать. И вообще с отладчиком и дурак может, а вы интуицую и свой жизненный опыт проявите, если так посодействовать хотите, чтобы найти решение. Вот ononim кое-что подсказал про ::close() — уже что-то хотя и не решает полностью проблему.
Re[7]: Непонятная ошибка при закрытии дескриптора файла
От: ononim  
Дата: 30.09.14 07:54
Оценка:
skl>>>Но стоит использовать линуксовые функции open/read/close (не важно блокируемые или нет), то начинаются проблемы, почему-то именно падает на close().
O>>а если писать не close(fd) а ::close(fd)?
skl>Этот способ с ::close(fd) заработал, т. е. в segmentation не падает и дескрипторы вроде в системе не исчерпываются.
skl>Не понял только я в чем тут суть?
В том что у класса FromFtpForm видимо есть метод close и вы вызывали его, а не системный close

skl>Однако при этом в буфер после чтения почему-то ничего не попадает, т. е. одни нули.

skl>Я пробовал также делать и ::open() и ::read(), но все равно в буфере нули.
потому что NONBLOCK так работает — если читать нечего то он ничего и не читает

skl>Что еще можете предложить?

Подумать над тем что выше написал.
Как много веселых ребят, и все делают велосипед...
Re[8]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 30.09.14 08:29
Оценка:
Здравствуйте, ononim, Вы писали:

skl>>>>Но стоит использовать линуксовые функции open/read/close (не важно блокируемые или нет), то начинаются проблемы, почему-то именно падает на close().

O>>>а если писать не close(fd) а ::close(fd)?
skl>>Этот способ с ::close(fd) заработал, т. е. в segmentation не падает и дескрипторы вроде в системе не исчерпываются.
skl>>Не понял только я в чем тут суть?
O>В том что у класса FromFtpForm видимо есть метод close и вы вызывали его, а не системный close

Класс FromFtpForm — это мой класс, но унаследован от QT-класса. Деструктор FromFtpForm пустой задан.


skl>>Однако при этом в буфер после чтения почему-то ничего не попадает, т. е. одни нули.

skl>>Я пробовал также делать и ::open() и ::read(), но все равно в буфере нули.
O>потому что NONBLOCK так работает — если читать нечего то он ничего и не читает

Почему нечего читать? Я передаю данные на USB — но они в буфер не попадают, а если NONBLOCK убрать, то тогда попадают.
Re[9]: Непонятная ошибка при закрытии дескриптора файла
От: smeeld  
Дата: 30.09.14 08:46
Оценка:
Здравствуйте, skl, Вы писали:


skl>Почему нечего читать? Я передаю данные на USB — но они в буфер не попадают, а если NONBLOCK убрать, то тогда попадают.


Это значит, что в момент записи, запись невозможна. При блокируемой записи засыпаем, пока
запись не станет возможной. При неблокируемой-возвращаемся. Вообще, что-то у Вас нет проверки
результата выполнения
errno=0;
size_t sz=write(fd....);
if(sz<0) if(errno!=EAGAIN) close(fd);
           else to_further();


while(errno==EAGAIN){ write(...); } не предлагаю, потому-то можно зацикливаться надолго.
Re[10]: Непонятная ошибка при закрытии дескриптора файла
От: skl  
Дата: 30.09.14 08:51
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Здравствуйте, skl, Вы писали:



skl>>Почему нечего читать? Я передаю данные на USB — но они в буфер не попадают, а если NONBLOCK убрать, то тогда попадают.


S>Это значит, что в момент записи, запись невозможна. При блокируемой записи засыпаем, пока

S>запись не станет возможной. При неблокируемой-возвращаемся. Вообще, что-то у Вас нет проверки
S>результата выполнения
S>
S>errno=0;
S>size_t sz=write(fd....);
S>if(sz<0) if(errno!=EAGAIN) close(fd);
S>           else to_further();  
S>


S>while(errno==EAGAIN){ write(...); } не предлагаю, потому-то можно зацикливаться надолго.


Причем здесь запись? Я читаю только из /dev/ttyACM0.
Re[11]: Непонятная ошибка при закрытии дескриптора файла
От: smeeld  
Дата: 30.09.14 09:01
Оценка:
Здравствуйте, skl, Вы писали:

skl>Причем здесь запись? Я читаю только из /dev/ttyACM0.


С чтением то же самое с точностью до write->read.
Re[9]: Непонятная ошибка при закрытии дескриптора файла
От: ononim  
Дата: 30.09.14 09:30
Оценка:
skl>>>>>Но стоит использовать линуксовые функции open/read/close (не важно блокируемые или нет), то начинаются проблемы, почему-то именно падает на close().
O>>>>а если писать не close(fd) а ::close(fd)?
skl>>>Этот способ с ::close(fd) заработал, т. е. в segmentation не падает и дескрипторы вроде в системе не исчерпываются.
skl>>>Не понял только я в чем тут суть?
O>>В том что у класса FromFtpForm видимо есть метод close и вы вызывали его, а не системный close
skl>Класс FromFtpForm — это мой класс, но унаследован от QT-класса. Деструктор FromFtpForm пустой задан.
Значит — ищите close в том у кого отнаследовались. В принципе еще есть вариант подтягивания close из какого нить неймспейса из текущих using namespace


skl>>>Однако при этом в буфер после чтения почему-то ничего не попадает, т. е. одни нули.

skl>>>Я пробовал также делать и ::open() и ::read(), но все равно в буфере нули.
O>>потому что NONBLOCK так работает — если читать нечего то он ничего и не читает
skl>Почему нечего читать? Я передаю данные на USB — но они в буфер не попадают, а если NONBLOCK убрать, то тогда попадают.
Я думаю они у вас попадают и тогда и тогда, просто в случае nonblocking чтения вы их не замечаете за кучей нулевых чтений ибо не проверяете код возврата read'а
Как много веселых ребят, и все делают велосипед...
Re[11]: Непонятная ошибка при закрытии дескриптора файла
От: rising_edge  
Дата: 30.09.14 11:00
Оценка:
Здравствуйте, skl, Вы писали:

S>>
S>>errno=0;
S>>size_t sz=write(fd....);
S>>if(sz<0) if(errno!=EAGAIN) close(fd);
S>>           else to_further();  
S>>

Вообще-то errno обнулять не нужно. Если write() завершается с ошибкой, то errno будет соответствующим. Если write() завершается нормально, errno проверять нельзя, ибо оно может быть каким угодно.
Re[12]: Непонятная ошибка при закрытии дескриптора файла
От: smeeld  
Дата: 30.09.14 11:06
Оценка:
Здравствуйте, rising_edge, Вы писали:

_>Здравствуйте, skl, Вы писали:


S>>>
S>>>errno=0;
S>>>size_t sz=write(fd....);
S>>>if(sz<0) if(errno!=EAGAIN) close(fd);
S>>>           else to_further();  
S>>>


_>Вообще-то errno обнулять не нужно.


Вообще-то желательно. В системных либах косяков много.

> Если write() завершается нормально, errno проверять нельзя, ибо оно может быть каким угодно.


if(sz<0) не видно?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.