2009-11-05 4 views
2

J'essaie de déboguer un problème dans mon code. J'ai un processus A qui fonctionne continuellement jusqu'à ce que je lui demande d'arrêter.Gestion des fichiers laissés par le code C++ sous Linux

Inside AI procédez comme suit:

  • montage partition/dev/sda1
  • open() // crée un fichier vide X
  • write() // écrire quelques octets il
  • close() // fermer le fichier
  • processFile() // Effectuer une opération
  • remove() // supprimer le fichier
  • umount/dev/sda1

note I test après chaque opération ci-dessus si elle a réussi ou non befor aller de l'avant. Quand je fais lsof | grep A il montre la poignée de fichier de X étant détenue par le processus A. Je vois aussi qu'il a un (supprimé). Cela m'empêche de démonter la partition. Pourquoi cela se passe-t-il et comment puis-je contourner ce problème?

EDIT: Merci à tous. Voici l'extrait du code:

tarFileDesc = _pSysCall->open("test.tar", O_CREAT | O_RDWR | O_APPEND, 0777);  
if (0 > tarFileDesc) 
    return false; 

... some logging here 

// Write http stream to tar file, istr is an argument to my function  
int read_buffer_size = 0;  
buffer = new char[4096];  
while (!istr.eof() && count < content_length) 
{  
    if ((content_length - count) >= 4096) 
     read_buffer_size = 4096; 
    else 
     read_buffer_size = content_length - count; 

    memset(buffer, 0, 4096); 
    istr.read(buffer, read_buffer_size); 
    std::streamsize in_bytes = istr.gcount(); 
    if (istr.fail() || istr.bad()) 
    { 
     status = false; 
     break; 
    } 

    if (write(tarFileDesc, buffer, in_bytes) != in_bytes) 
    { 
     status = false; 
     break; 
    } 
    count += in_bytes; 
} 
// Cleanup buffer 
delete[] buffer; 

if ((0 > tarFileDesc) && (0 != close(tarFileDesc))) 
    return false; 

if (0 != system("tar C /test -xvf test.tar")) 
    return false; 

if (0 != remove("test.tar")) 
     return false; 

Remarque J'ai même essayé de faire juste l'ouvrir, fermer et supprimer. Mais je vois toujours la poignée maintenue par processus.

+1

Veuillez ajouter du code, pas de méta-code. Les problèmes de verrouillage ne peuvent généralement pas être résolus par méta-code. Réduire le code d'origine, puis nous pouvons essayer de le déboguer. – Thorsten79

+0

Vous voyez le fichier handle du fichier X appartenant à votre processus * après * vous avez supprimé le fichier? Je ne suis pas un expert, mais cela semble étrange. Pourriez-vous emballer votre problème dans quelques lignes de code? – mkluwe

+2

@mkluwe - Les UNIX prennent en charge ce comportement. Le même processus ou un processus différent peut supprimer le fichier alors qu'il est ouvert. Le fichier peut toujours être écrit à travers les poignées ouvertes, mais dès que toutes les poignées du fichier sont fermées, le fichier est supprimé. Toute tentative de nouvelle ouverture sur un fichier dans cet état est refusée. Donc, si le fichier n'est pas fermé complètement ou correctement dans le processus, ce serait valide. –

Répondre

0

Vous devrez probablement poster du code. Mais voici une astuce pour vous - si vous créez un fichier temporaire sous Unix/Linux/Mac OS X, vous pouvez le supprimer IMMEDIATEMENT et vous pouvez toujours y écrire, le lire, etc, mais dès que vous le fermez, il sera allez-vous en. Il va également disparaître si une erreur tue votre programme avant que vous ne parveniez à le fermer.

1

Merci à tous. Voici l'extrait du code:

tarFileDesc = _pSysCall->open("test.tar", O_CREAT | O_RDWR | O_APPEND, 0777);  
if (0 > tarFileDesc) 
    return false; 

... some logging here 

// Write http stream to tar file, istr is an argument to my function  
int read_buffer_size = 0;  
buffer = new char[4096];  
while (!istr.eof() && count < content_length) 
{  
    if ((content_length - count) >= 4096) 
     read_buffer_size = 4096; 
    else 
     read_buffer_size = content_length - count; 

    memset(buffer, 0, 4096); 
    istr.read(buffer, read_buffer_size); 
    std::streamsize in_bytes = istr.gcount(); 
    if (istr.fail() || istr.bad()) 
    { 
     status = false; 
     break; 
    } 

    if (write(tarFileDesc, buffer, in_bytes) != in_bytes) 
    { 
     status = false; 
     break; 
    } 
    count += in_bytes; 
} 
// Cleanup buffer 
delete[] buffer; 

if ((0 > tarFileDesc) && (0 != close(tarFileDesc))) 
    return false; 

if (0 != system("tar C /test -xvf test.tar")) 
    return false; 

if (0 != remove("test.tar")) 
     return false; 

Remarque J'ai même essayé d'ouvrir, de fermer et de retirer. Mais je vois toujours la poignée maintenue par processus.

+0

S'il vous plaît modifier la question au lieu d'ajouter une réponse – Hasturkun

+0

je ne suis pas sûr qu'il peut avec sa réputation? –

+1

À l'OP ... vous pouvez supprimer ce commentaire maintenant; J'ai mis ce code dans la question originale. –

5

Le problème se trouve dans ces lignes:

if ((0 > tarFileDesc) && (0 != close(tarFileDesc))) 
    return false; 

Ce ne fermera le descripteur de fichier si tarFileDesc < 0. Ce que vous voulez dire si tarFileDesc >= 0 puis fermez comme il est un descripteur de fichier valide, alors essayez de changer ce code:

if ((0 > tarFileDesc) || (0 != close(tarFileDesc))) 
    return false; 

De cette façon, vous retournez false si le descripteur de fichier est invalide, sinon vous retournez false si vous êtes incapable de le fermer.

+0

HA! C'est ce que vous obtenez lorsque vous tournez des expressions pour faire le travail d'un avertissement de compilateur. :-D – DevSolar

+0

Oh, et c'est absolument la bonne réponse bien sûr. – DevSolar

0

Ce regard suspect:

if ((0 > tarFileDesc) && (0 != close(tarFileDesc))) 
    return false; 

regard tourné vers le haut de votre code, vous faites déjà un chèque de 0 > tarFileDesc, et si vrai faux retour juste à ce moment-là. Donc je pense que cette partie du chèque est redondante? c'est à dire., devrait-il simplement lire:

if (0 != close(tarFileDesc))) 
    return false; 
+0

Fermer ... voir la réponse d'Anacrolix. – DevSolar

+0

@DevSolar - en désaccord; le chèque est toujours redondant. Pourquoi est-il nécessaire lorsque le chek pour tarFileDesc a déjà été effectué et la fonction est sortie? –

+0

un bon point Chris J, cependant l'OP utilise un paradigme de nettoyage C où il veut surtout vérifier et désinitialiser à la fin de la fonction. s'il devait changer la fonction plus tard, la vérification d'un descripteur de fichier valide pourrait à nouveau être nécessaire. si quelque chose que je le mets à un oubli de la part de l'OP. la première vérification que le descripteur de fichier est invalide devrait plutôt aller à la section de nettoyage au lieu de retourner. –

Questions connexes