Этот вопрос чем-то похож на Неверный файловый дескриптор, но это совсем не то же самое. Я знаю, что это плохой вопрос (возможно, слишком локализованный), но я не могу понять это, и теперь у меня нет никаких идей.
Введение
У меня есть поток менеджера, который запускает 75 других потоков. Каждый из этих потоков делает много вещей, поэтому я опишу только соответствующие.
Обратите внимание: если я запускаю только несколько тем - например, 3, или 5, или 10, эта ошибка не появляется! Это наводит меня на мысль, что это какая-то проблема с многопоточностью, но похоже, что это не так. И вы поймете почему в следующих разделах.
Итак, в следующих двух случаях ИНОГДА я получаю эту ошибку Bad file descriptor
:
Дело 1
Ошибка появляется в TinyXML
Есть файл xml, который нужен всем потокам. Все эти потоки используют TinyXML
для разбора файла. ВСЕ эти потоки используют этот файл ТОЛЬКО ДЛЯ ЧТЕНИЯ! (я знаю, что это можно оптимизировать, но неважно).
Итак, код, вызывающий ошибку Bad file descriptor
, таков:
// ...
// NOTE: this is LOCAL, other threads do NOT have access to it
TiXmlDocument doc;
doc.LoadFile( filename );
// and here's the LoadFile:
bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
{
//...
FILE* file = fopen( value.c_str (), "rb" );
if ( file )
{
// this IS executed, so file is NOT NULL for sure
bool result = LoadFile( file, encoding );
//...
}
//...
}
bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
{
// ...
long length = 0;
fseek( file, 0, SEEK_END );
// from the code above, we are SURE that file is NOT NULL, it's valid, but
length = ftell( file ); // RETURNS -1 with errno: 9 (BAD FILE DESCRIPTOR)
// how is this possible, as "file" is not NULL and it appears to be valid?
// ...
}
случай 2
Это немного сложнее. Я убрал проверку возвращаемых значений, но они есть в моем реальном коде, так что это не проблема
int hFileR = open( sAlarmFileName.c_str(), O_CREAT | O_RDONLY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH );
// hFileR is > 0 for sure, so success
flock( hFileR, LOCK_EX ) /* the result is > 0 for sure, so success*/
// read the file into a string
while( (nRes = read(hFileR, BUFF, MAX_RW_BUFF_SIZE)) > 0 ) // ...
//Write new data to file: reopen/create file - write and truncate mode
int hFileW = open( sAlarmFileName.c_str(),
O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR |
S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH );
// hFileW is > 0 for sure, so success
do
{
int nWrtRes = write( hFileW,
szText + nBytesWritten, nSize - nBytesWritten );
// nWrtRes is always >= 0, so success
nBytesWritten += nWrtRes;
}
while( nSize > nBytesWritten );
close( hFileW ); // this one is successful too
if( flock(hFileR, LOCK_UN) == -1 )
{
// THIS FAILS and executes _Exit( FAILURE );
}
if( close( hFileR ) < 0 )
{
// if the previous one do not fail, this one is successful too
}
Извините за длинный вопрос. Есть идеи?
fseek()
перед переходом кftell()
. - person WhozCraig   schedule 07.12.2012FILE *
какой-то другой поток закрыл базовый файловый дескриптор. Наиболее вероятной причиной этого является двойное закрытие где-то еще в коде. - person David Schwartz   schedule 07.12.2012close
для файлового дескриптора другого потока, чтобы остановить этот другой поток. Например, код TCP, который имеет поток чтения и поток записи, может по идее иметь какой-то другой поток, вызывающийclose
для дескриптора, чтобы сделать потоки чтения и записи неудачными. Среди многих ужасных вещей, которые это вызывает, если другой поток получает тот же дескриптор как раз в тот момент, когда поток записи собирается записать, поток записи может записать конфиденциальные данные в неправильное соединение. Используйтеshutdown
. - person David Schwartz   schedule 07.12.2012