Что делает выбор (2), если Вы закрываетесь (2) дескриптор файла в отдельном потоке?

increment_item() принимает Container по ссылке, и item нельзя перемещать (или «использовать»), пока оно находится за ссылкой, поскольку increment() принимает Item по значению. Самый быстрый способ исправить это - сделать Item типом Copy. Это запустит копию, а не движение (т. Е. Потребляет). детская площадка

#[derive(Clone, Copy)]
struct Item {
    x: u32,
}
...
...

Для получения дополнительной информации, пожалуйста, обратитесь Копировать

24
задан Kara 20 January 2017 в 19:38
поделиться

4 ответа

Из какого-то дополнительного расследования выясняется, что оба dwc и оба правы.

Ответ обоих на вопрос сводится к следующему: это неопределенное поведение. Это не значит, что это непредсказуемо, но разные ОС делают это по-разному. Может показаться, что системы, такие как Solaris и HP-UX, возвращаются из select(2) в этом случае, но Linux не основывает этот пост в списке рассылки linux-kernel от 2001 года.

Аргумент в списке рассылки linux-kernel заключается в том, что на него нельзя полагаться (и он не работает). В случае Linux вызов close(2) для файлового дескриптора фактически уменьшает счетчик ссылок на него. Поскольку существует вызов select(2) также со ссылкой на него, fd останется открытым и ожидает ввода, пока не вернется select(2). Это в основном ответ dwc . Вы получите событие в дескрипторе файла, а затем оно будет закрыто. Попытка чтения из него приведет к EBADF, при условии, что fd не был переработан. (Обеспокоенность, которую МаркР высказал в своим ответом , хотя я думаю, что его, вероятно, можно избежать в большинстве случаев при надлежащей синхронизации.)

Так что спасибо всем за помощь.

21
ответ дан Community 28 November 2019 в 23:55
поделиться

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

Однако делая, который является очень плохой практикой так или иначе, поскольку у Вас всегда были бы потенциальные условия состязания как другой , дескриптор файла с тем же числом мог быть сразу открыт еще одним потоком после, другое 2-е закрыло его, затем поток выбора закончит тем, что ожидал на неправильном.

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

6
ответ дан MarkR 28 November 2019 в 23:55
поделиться

Системный вызов select - это способ подождать, пока дескрипторы файлов не изменят состояние, в то время как программам больше нечего делать. Основное использование предназначено для серверных приложений, которые открывают несколько файловых дескрипторов, а затем ждут, что с ними что-то будет делать (принимают новые соединения, читают запросы или отправляют ответы). Эти файловые дескрипторы будут открыты в неблокирующем режиме io, так что процесс сервера не будет зависать в системном вызове в любое время.

Это дополнительно означает, что нет необходимости в отдельных потоках, потому что вся работа, которая может быть выполнена в потоке, может быть выполнена до вызова select. И если работа занимает больше времени, чем ее можно прервать, выберите вызов с тайм-аутом = {0,0}, дескрипторы файлов обрабатываются, а затем работа возобновляется.

Теперь вы закрываете файловый дескриптор в другом потоке. Почему у вас вообще есть этот дополнительный поток, и почему он должен закрывать файловый дескриптор?

Стандарт POSIX не дает никаких подсказок, что происходит в этом случае, поэтому то, что вы делаете, - НЕОПРЕДЕЛЕННОЕ ПОВЕДЕНИЕ , Ожидайте, что результат будет очень разным в разных операционных системах и даже в разных версиях одной и той же ОС.

С уважением, Бодо

5
ответ дан Bodo Thiesen 28 November 2019 в 23:55
поделиться

Это немного сбивает с толку, что вы спрашиваете ...

Функция Select () должна вернуться после «интересного» изменения. Если close () просто уменьшило счетчик ссылок, а файл все еще был открыт для записи где-то, то нет никаких причин для выбора select ().

Если другой поток сделал close () для единственного открытого дескриптора, он становится более интересным, но мне нужно увидеть простую версию кода, чтобы увидеть, действительно ли что-то не так.

2
ответ дан dwc 28 November 2019 в 23:55
поделиться
Другие вопросы по тегам:

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