[Langage C] Close () Il est dangereux de réessayer en cas d'échec

introduction

En tant qu'appel système pour fermer le descripteur de fichier close()Est fourni. Par conséquent, j'écrirai sur les pièges de l'appel système fermé qui sont souvent négligés.

#include <unistd.h>

int close(int fd);

EINTR vous invite à un piège

Par exemple, lors de l'appel d'un appel système d'E / S de fichier ou d'une fonction de bibliothèque eintrEst gênant, et il y a des cas où une erreur se produit lorsqu'un appel de fonction est interrompu.

EINTR Voir appel de fonction interrompu (POSIX.1); signal (7).

Référence: Manuel du programmeur Linux --ERRNO

Dans ce cas, même s'il échoue comme suit, s'il s'agit de EINTR, Il existe une solution de contournement pour fournir une fonction wrapper pour réessayer et éviter l'échec du traitement dans EINTR.

/* wrapper function of send () */
ssize_t send_wrap(int sockfd, const void *buf, size_t len, int flags)
{
  int res = 0;
  do {
    res = send(sockfd, buf, len, flags);
  } while ((res == -1) && (errno == EINTR));
  return res;
}

Il y a aussi un échec dû à ʻEINTR` dans close (). Cependant, les tentatives sur l'appel système ** close () sont dangereuses. ** **

Risque de nouvelle tentative en cas d'échec de close ()

Alors, pourquoi est-il dangereux de réessayer lorsque close () échoue? Par exemple, dans le cas du multithreading, il est possible de fermer le fd réutilisé par un autre thread.

Le noyau Linux publie fd au début du processus dans close (), Le traitement qui peut provoquer une erreur est situé dans la seconde moitié de close ().

En d'autres termes, le processus est renvoyé comme une erreur, mais fd est ** libéré **, donc S'il est multi-thread, ** un autre thread peut réutiliser le fd **, Il existe un risque que ** le fichier fd soit fermé ** s'il est réessayé.

Conclusion

D'après ce qui précède, on peut dire qu'il vaut mieux ne pas réessayer l'appel système close () quand il échoue.

référence

http://man7.org/linux/man-pages/man2/close.2.html

Recommended Posts

[Langage C] Close () Il est dangereux de réessayer en cas d'échec
Introduction à Protobuf-c (langage C ⇔ Python)
Lorsque vous souhaitez l'utiliser tel quel lorsque vous l'utilisez avec lambda memo
Il est préférable d'utiliser Weight Initializer lors de l'initialisation avec HeNormal avec Chainer
Il était dangereux de spécifier un chemin relatif lors de la génération d'un lien symbolique
Qu'est-ce qu'une bibliothèque en langage C? Quelles informations sont ouvertes au public?
Utilisation pratique des couches lors du chargement de bibliothèques sur Lambda
N'est-il pas recommandé d'utiliser pip directement?
Il est plus pratique d'utiliser csv-table lors de l'écriture d'une table avec python-sphinx
[OpenCV] Lorsque vous voulez vérifier s'il est lu correctement avec imread