2017-08-20 7 views
4

Je ne suis pas un expert en C et je cherche des conseils pour rendre mon programme plus robuste et plus fiable. Juste pour donner un peu de contexte: J'ai écrit un programme pour faire un calcul scientifique qui dure assez longtemps (environ 20h) que je suis en train d'exécuter sur un grand cluster Linux Linux HPC utilisant un système de planification SLRUM et des systèmes de fichiers montés NFS. Ce qui semble se passer est que quelque temps pendant les 20h la connexion au système de fichiers devient obsolète (sur l'ensemble de la machine, indépendant de mon programme) et la première tentative d'ouverture & prend un temps très long et cela se traduit par un Segfault évoqué erreur sous-jacente que je n'ai pas encore été en mesure de traquer avec précision. Voici un fichier minimal qui reproduit au moins conceptuellement l'erreur: Le programme démarre, ouvre un fichier et tout fonctionne. Le programme effectue un long calcul (simulé par sleep()), essaye d'ouvrir & pour réécrire dans le même fichier et échoue. Quelles sont les conventions pour rendre mon code plus robuste et écrire de manière fiable mes résultats dans un fichier sans crash?Comment écrire de manière robuste sur un NFS lent et peu fiable

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(int argc, char **argv) { 
    // Declare variables 
    FILE *outfile; 
    char outname[150] = "result.csv"; 

    // Open file for writing 
    printf("CHECKING if output file '%s' is writable?", outname); 
    outfile=fopen(outname, "w"); 
    if (outfile == NULL) { 
     perror("Failed: "); 
     exit(EXIT_FAILURE); 
    } 
    fclose(outfile); 
    printf(" PASSED.\n"); 

    // Do some computation that takes really long (around 19h) 
    sleep(3); 

    // Open file again and Write results 
    printf("Writing results to %s ...", outname); 
    outfile=fopen(outname, "w"); 
    if (outfile == NULL) { 
     perror("Failed writing in tabulate_vector_new: "); 
     exit(EXIT_FAILURE); 
    } 
    fprintf(outfile, "This is the important result.\n"); 
    fclose(outfile); 

    printf(" DONE.\n"); 
    return 0; 
} 
+2

Probablement pas le problème, mais 'fclose()' renvoie '0' si le fichier a été fermé avec succès; il semble toujours utile de cocher ces cases évidentes lors du dépannage des problèmes d'E/S. –

+1

Voici une recette: prenez un bon administrateur réseau, motivez-le pour résoudre le problème NFS. Répétez jusqu'à ce que terminé. – ddbug

+1

Je ne vois pas pourquoi le programme que vous avez inclus aurait une erreur de segmentation, sauf si l'exécutable se trouve sur un système de fichiers NFS qui est obsolète. Si vous pouvez l'exécuter sous un débogueur, dites-nous sur quelle ligne l'erreur se produit. –

Répondre

0

Il semble étrange que votre programme se sépare en raison d'un problème NFS. Je m'attendrais à ce qu'il pende indéfiniment, pas crash. Ceci étant dit, je suggérerais de forker un nouveau processus pour vérifier si la monture NFS fonctionne. De cette façon, votre code important ne sera pas directement impliqué dans le test du système de fichiers problématique. Quelque chose comme l'approche suivante peut être utile:

pid_t pid = fork(); 

if (pid == -1) 
{ 
    // error, failed to fork(). should probably give up now. something is really wrong. 
} 
else if (pid > 0) 
{ 
    // if the child exits, it has successfully interacted with the NFS file system 
    wait(NULL); 
    // proceed with attempting to write important data 
} 
else 
{ 
    // we are the child; fork df in order to test the NFS file system 
    execlp("df", "df", "/mnt", (char *)NULL) 
    // the child has been replaced by df, which will try to statfs(2) /mnt for us 
} 

Le concept général est que nous utilisons la commande df pour vérifier si le système de fichiers NFS (que je suppose est à /mnt) travaille. Si cela ne fonctionne pas temporairement, df devrait se bloquer jusqu'à ce qu'il recommence à fonctionner, puis quitter, en retournant le contrôle à votre programme. Si vous pensez que df peut être suspendu pour toujours, vous pouvez améliorer mon exemple en utilisant alarm(2) pour attendre un certain laps de temps, probablement au moins quelques minutes, après quoi vous pouvez réessayer en cours d'exécution df. Notez que cela pourrait entraîner des processus zombie df qui traînent. En fin de compte, la solution correcte est d'essayer d'obtenir un serveur NFS plus fiable, mais jusqu'à ce que vous puissiez le faire, j'espère que c'est utile.