Не безопасно закрывать файловый дескриптор, когда его может использовать другой поток, по нескольким причинам.
Как вы обнаружили, некоторые системные вызовы, которые могут блокировать ожидание файлового дескриптора, могут вести себя непредсказуемым образом, если этот файловый дескриптор закрыт.
Но есть и другие проблемы. Предположим, что первый поток закрывает файловый дескриптор как раз перед тем, как второй поток вводит в него вызов read()
. Предположим также, что третий поток одновременно открывает файл или сокет. Новый дескриптор файла получит тот же номер, что и тот, который был только что закрыт. Второй поток будет читать из неправильного файлового дескриптора!
В общем, вам нужно убедиться, что только один поток работает с дескриптором файла одновременно. Потоки должны «владеть» файловыми дескрипторами. Вы можете передавать права собственности от одного потока другому, но каждый должен владеть только одним.
Если вам нужно отменить операции, вам нужно использовать неблокирующий ввод-вывод и такие вещи, как select()
, когда вам нужно заблокировать ожидание данных. Кроме того, вам необходимо включить межпотоковый канал связи (например, канал) в вызов select()
, который будет механизмом, посредством которого один поток отправляет запрос другому, чтобы закрыть один из своих файловых дескрипторов.
Вам также следует обратить внимание на диспетчеризацию ввода-вывода или асинхронные механизмы, такие как управляемый цикл выполнения NSFileHandle
.