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: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, skl, Вы писали:
skl>1) Непонятная проблема происходит при закрытии дескриптора файла (открытого файла на чтение) в коде на C++ ниже (ОС Linux). Это метод класса, который skl>вызывается периодически по таймеру. Если я вставляю в конце этой функции close(barcode_fd), то программа падает в segmentation fault, а если оставляю без оператора close, то программа работает правильно, но в системе со временем исчерпываются все дескрипторы файлов, что очевидно, т. к. они не закрываются в программе.
Странное что-то. Может, где-то в другом месте рушится стек или куча, а close всего лишь случайным образом оказался триггером? Падение происходит в самом close() или где-то дальше по коду? Если дальше, то что возвращает close()? (И read() заодно уж.)
А если временно переписать на fopen/fread/fclose, проблема останется?
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, 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]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, 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]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, Zhendos, Вы писали:
Z>ИМХО ошибка не в приведенном коде, а где-то еще. Z>Используйте valgrind или gcc + "-fsanitize=address"
Это практически невозможно сделать, т. к. я кросскомпилирую (на x86 компьютере) свой код специальным arm-gcc компилятором (для arm9 машины). Выполнить код и посмотреть его работу я могу только на том устройстве для которого кросскомпилирую код (установить туда какие-то средства отладки практически невозможное дело, использую просто отладочные вывод с помощью printf в консоль).
Код довольно-таки обширный и проблем я никаких не знал до сих пор, так что на кросскомпилятор не хочу грешить.
Re[3]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, 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: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, skl, Вы писали:
skl>2) Я понимаю, что это скорее сишный код в методе, но я не знаю как с помощью файловых потоков С++ задать неблокируемый режим для файла на чтение (т. е. флаг O_NONBLOCK). Буду благодарен за подсказку как это сделать при помощи файловых потоков С++.
Ты зовешь read() и не дожидаясь его завершения — close() и более того разрушаешь буффер. понятно что упадет где-нибудь.
Мне кажется тв не понимаешь как работатет O_NONBLOCK — т.е. не блокирующий IO
Здравствуйте, 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]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, 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]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, 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]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, 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]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, skl, Вы писали:
skl>Это практически невозможно сделать, т. к. я кросскомпилирую (на x86 компьютере) свой код специальным arm-gcc компилятором (для arm9 машины). Выполнить код и посмотреть его работу я могу только на том устройстве для которого кросскомпилирую код (установить туда какие-то средства отладки практически невозможное дело, использую просто отладочные вывод с помощью printf в консоль).
JTAG skl>Код довольно-таки обширный и проблем я никаких не знал до сих пор, так что на кросскомпилятор не хочу грешить.
Не греши, собирай в виртуалке.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[3]: Непонятная ошибка при закрытии дескриптора файла
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]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, skl, Вы писали:
skl>Здравствуйте, Zhendos, Вы писали:
skl>Про std::memset — конечно лучше. В данном коде я просто вручную забил нулями буфер через for чтобы быть уверенным что дело в не в memset().
Не, я имел ввиду, что странно не только не использование memset, но и использование его замены.
Ведь read запишет сколько сможет и вернет количество записанных байт, так что
этот код выглядит как:
int i;
i = 10;//(1)
i = 15;
(1) конечно не повредит, но и смысла в нем никакого.
Re[5]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, 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]: Непонятная ошибка при закрытии дескриптора файла
skl>Но с буфером-то я произвожу после чтения кое-какие манипуляции (этот код убран мной в форуме) и мне желательно чтобы строка нулем заканчивалась, и я не уверен что после чтения read в строке будет нуль в конце, поэтому и забиваю нулями буфер заранее. skl>Вообще в данном случае наверное лучше инициализировать так:
skl>char buf_barcode[150] = { 0 };
skl>Но это к теме не относится.
Чтобы было понятно в коде я хочу периодически делать чтение этого файла на предмет появления новых данных, которые читаю и вывожу в окно (QT), естественно я не хочу чтобы на чтении этого файла блокировалась вся программа, поэтому указываю NONBLOCK. Отдельный поток не очень хочется отводить. Не работает именно с линуксовыми функциями open/read (без разницы NONBLOCK или без NONBLOCK), а с функциями c++ для работы с файлами программа не падает, но не понятно как nonblock указать.
Re[6]: Непонятная ошибка при закрытии дескриптора файла
skl>Это кстати USB: /dev/ttyACM0.
skl>Чтобы было понятно в коде я хочу периодически делать чтение этого файла на предмет появления новых данных, которые читаю и вывожу в окно (QT), естественно я не хочу чтобы на чтении этого файла блокировалась вся программа, поэтому указываю NONBLOCK. Отдельный поток не очень хочется отводить.
Если не хочется поток новый создавать (я бы создал),
то можно использовать QSocketNotifier, и не переоткрывать файл переодически,
а открыть один раз.
Re[7]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, Zhendos, Вы писали:
Z>Здравствуйте, skl, Вы писали:
skl>>Это кстати USB: /dev/ttyACM0.
skl>>Чтобы было понятно в коде я хочу периодически делать чтение этого файла на предмет появления новых данных, которые читаю и вывожу в окно (QT), естественно я не хочу чтобы на чтении этого файла блокировалась вся программа, поэтому указываю NONBLOCK. Отдельный поток не очень хочется отводить.
Z>Если не хочется поток новый создавать (я бы создал), Z>то можно использовать QSocketNotifier, и не переоткрывать файл переодически, Z>а открыть один раз.
Не уверен что QSocketNotifier есть в QT2 (не использую QT4-5 т. к. медленно работает на моем устройстве). Но упоминание про QT навело меня сейчас на мысль, что QT создает свои потоки (для своих нужд) и соответственно мой код может работать в нескольких потоках созданных этой библиотекой. Закрытие close() в одном из них естественно вызывает сбой, т. к. тот же файл открыт в других ее потоках. Попробую завтра этот код поместить в отдельный Singelton и напишу если получится.
Re[6]: Непонятная ошибка при закрытии дескриптора файла
Здравствуйте, skl, Вы писали:
skl>Но с буфером-то я произвожу после чтения кое-какие манипуляции (этот код убран мной в форуме) и мне желательно чтобы строка нулем заканчивалась, и я не уверен что после чтения read в строке будет нуль в конце, поэтому и забиваю нулями буфер заранее.
Похоже, что выходите за пределы массива при 'манипуляциях' и затираете переменную int barcode_fd;. printf("%d\n", barcode_fd) после open и printf перед close могут помочь в поиске ошибки.