RE: Comportement mystérieux d'un programme C sur Debian 7

トップ ページ

このメッセージに返信
著者: BOITEUX, Frederic
日付:  
To: guilde@guilde.asso.fr
題目: RE: Comportement mystérieux d'un programme C sur Debian 7
    Bonjour Raphaël,

  Je pensais que cette possibilité de ne pas tout écrire en une seule fois était liée aux fonctions de plus bas-niveau write() [et read()] et pas aux fonctions fwrite() et fread()… mais quoi qu'il en soit, le errno ici n'est pas significatif, car la fonction fwrite() a bien renvoyé la valeur 1, ce qui signifie qu'elle a bien écrit la donnée demandée… Le problème est ailleurs…

    Merci tout de même,
        Fred.

-----Message d'origine-----
De : Raphaël Dorado [mailto:rdorado@free.fr] 
Envoyé : vendredi 12 février 2016 18:21
À : guilde@???
Objet : Re: Comportement mystérieux d'un programme C sur Debian 7


Bonsoir,

Je pense que le problème n'est pas lié à Debian spécifiquement, mais plutôt à la gestion des erreurs système sous Unix en général.

>> 15:13:04.349 =>ma_pub_sauve() : fwrite() done st=1, *errno=4*


Le ERRNO sur fwrite() est "4", une EINTR (interrupted system call), ce qui provient en général d'une I/O d'un filesystem sur socket / réseau.

Cela signifie qu'une interruption prioritaire a pris le dessus sur le
syscall() sous-jacent (write()), et que l'opération demandée n'a pas pu être effectuée. Il suffit en général de répéter l'opération, mais si problème sérieux (créseau cassé) il faut éviter d'avoir une attente "trop" active.

Il faut donc enrober les fonctions I/O (f)open/(f)write/(f)close/(f)stat du genre (pour fwrite):

size_t my_fwrite(const void *ptr, size_t wsize, size_t nmemb,FILE *stream) {
     size_t      sz;
     unsigned    delay = 0;

     /* Tant que erreur I/O ET que errno == EINTR, attendre 1 milliseconde */
     while( (sz = fwrite(ptr , wsize , nmemb , stream) < 0 && errno == EINTR) )
     {
         if (delay == 0)
         {
             /* La première fois, on ré-essaie tout de suite  */
             /* et on active le delai pour les fois suivantes */
             delay = 1000;
         }
         else
         {
             /* Si réseau cassé, ne pas occuper le CPU */
             /* A partir de la 2eme tentative échouée, */
             /* on attendra 1 ms avant chaque essai    */
             usleep(delay);
         }
     }

     return(sz);
}



--Raf


Le 12/02/2016 15:32, BOITEUX, Frederic a écrit :

>     Bonjour Jérémy,
>
> Pour l'usage de rename(), ce serait judicieux, en effet, mais on a 
> parfois gardé des habitudes héritées de systèmes Unix anciens :-) En 
> tout cas, le souci est avant, dans la création du fichier temporaire, 
> pas dans son renommage… et cela n'arrive que de temps à autre…
>
> [et pour l'espace dans le nom de fichier, il n'est pas dans le log 
> original, j'ai dû l'introduire en copiant/collant :-(  ]
>
>     Cordialement,
>         Fred.
>
> -----Message d'origine-----
> De : Jérémy Bobbio [mailto:lunar@debian.org] Envoyé : vendredi 12 
> février 2016 14:46 À : ML Guilde (guilde@???) Objet : Re: 
> Comportement mystérieux d'un programme C sur Debian 7
>
> BOITEUX, Frederic:
>>   sur un serveur en Debian 7 (7.9), une application écrite en C/C++ 
>> effectue [entre autres] toutes les 20 secondes une mise à jour d'un 
>> gros fichier (~ 30 Mo) en écrivant des données dans un fichier 
>> temporaire, avant de supprimer le fichier nominal pour le remplacer 
>> par ce fichier temporaire par des unlink() / link().
>
> Je suis confus. Pourquoi ne pas utiliser rename(2)? J'ai justement le seul appel système qui garantie qu'on peut remplacer un fichier par une nouvelle version de manière atomique.
>
>> On obtient des traces du genre :
>>
>> 15:13:04.349 =>ma_pub_sauve() : fwrite() done st=1, errno=4
>> 15:13:04.360 =>ma_pub_sauve() : fclosed done status=0 errno=4
>> 15:13:04.360 write file tmp file not found '/appli/ datas.d/mlp01/mlp01.tmp'
>                                                       ^
>
> Il est normal l'espace, là ?
>
> (Si c'est un vrai répertoire que quelqu'un·e a nommé '\x20datas.d', je 
> suggère d'expliquer à cette personne que ce genre de blagues ne fait 
> rire personne.)
>



This message contains information that may be privileged or confidential and is the property of the Capgemini Group. It is intended only for the person to whom it is addressed. If you are not the intended recipient, you are not authorized to read, print, retain, copy, disseminate, distribute, or use this message or any part thereof. If you receive this message in error, please notify the sender immediately and delete all copies of this message.