POSIX / UNIX: Como fechar de forma confiável um descritor de arquivo

Problema:

Após um syscall close () que falha com EINTR ou EIO, não é especificado se o arquivo foi fechado. (http://pubs.opengroup.org/onlinepubs/9699919799/) Em aplicativos multithread, tentar novamente o fechamento pode fechar arquivos não relacionados abertos por outros threads. Não tentar novamente o fechamento pode resultar na acumulação de descritores de arquivos abertos inutilizáveis. Uma solução limpa pode envolver a chamada de fstat () no descritor de arquivo recém-fechado e um mecanismo de bloqueio bastante complexo. Além disso, serializar todas as chamadas de abrir / fechar / aceitar / ... com um único mutex pode ser uma opção.

Essas soluções não levam em conta que as funções da biblioteca podem abrir e fechar arquivos por si mesmas de uma maneira incontrolável, por exemplo, algumas implementações de arquivos abertos std :: thread :: hardware_concurrency () no sistema de arquivos / proc.

Os fluxos de arquivos como na seção padrão C ++ [file.streams] não são uma opção.

Existe um mecanismo simples e confiável para fechar arquivos na presença de vários threads?

Editar% s:

Arquivos regulares: Embora na maioria das vezes não haja descritores de arquivos abertos inutilizáveis, duas condições podem desencadear o problema: 1. Sinais emitidos em alta frequência por alguns malwares 2. Sistemas de arquivos de rede que perdem a conexão antes que os caches sejam liberados.

Soquetes: de acordo com Stevens / Fenner / Rudoff, se a opção de soquete SO_LINGER estiver configurada em um descritor de arquivo referente a um soquete conectado e, durante um close (), o temporizador transcorrerá antes que a sequência de desligamento FIN-ACK seja concluída, close () falhe como parte do procedimento comum. O Linux não mostra esse comportamento; no entanto, o FreeBSD mostra e também define errno como EAGAIN. Pelo que entendi, nesse caso, não é especificado se o descritor de arquivo é invalidado. Código C ++ para testar o comportamento:http://www.longhaulmail.de/misc/close.txt A saída do código de teste parece uma condição de corrida no FreeBSD para mim, se não for, por que não?

Pode-se considerar sinais de bloqueio durante as chamadas para fechar ().