2009-07-15 4 views
9

j'ai hérité du code:Process Builder waitFor() question et les limites Ouvrir le fichier

Process p = new ProcessBuilder("/bin/chmod", "777", path).start(); 
p.waitFor(); 

Fondamentalement, il est pour une raison ancienne et très basée voodoo pour stocker des paires clé/valeur sur le disque sous forme de fichiers. Je ne veux pas vraiment y aller.

Cependant, je suis parti avec un tas d'exceptions IO:

Exception :Cannot run program "/bin/chmod": java.io.IOException: error=24, Too many open files 
Message: Cannot run program "/bin/chmod": java.io.IOException: error=24, Too many open files 

Et par un groupe que je veux dire dans les domaines de 10k - millions

Je sens l'appel waitFor était d'arrêter ceux-ci se produisent en attendant que le processus le termine et sorte en arrière, mais je pense que le chmod retourne un résultat avant que le fichier ne soit effectivement fermé. Est-ce que quelqu'un sait si cela serait la cause de ces exceptions? Mon autre inclination est que l'ouverture et la fermeture de milliers de fichiers ne se produisent pas assez rapidement sur le côté Java et qu'il se passe quelque chose d'autre, peut-être quelque chose comme ça il y a une forme de tampon de fichiers qui n'est pas être effacé lorsque fw.close() est appelé. Je suis assez nouveau à Java et c'était un enfer bizarre qui m'a fait perplexe. (heureusement, l'application fonctionne toujours ... après avoir craché un très gros fichier journal qui est)

Quelqu'un d'autre peut penser à un moyen de contourner ce problème, effacer les tampons ou augmenter la limite d'ouverture de fichiers à quelque chose où le jvm peut se maintenir avec soi-même (en supposant que ce soit le problème)

+0

Quel est votre système d'exploitation cible (et sa version).Voir ceci: http://unix.derkeiler.com/Newsgroups/comp.unix.solaris/2007-02/msg00873.html –

+0

debian, il semble être effacé de uname. sera la dernière stable. – Louis

Répondre

14

Je suppose que vous exécutez ces commandes chmod dans une boucle - sinon je ne vois pas pourquoi vous auriez tant d'exceptions. Il est possible que vous soyez dans une impasse parce que vous ne lisez pas la sortie des processus générés. Cela me rappelait certainement les jours pré-ProcessBuilder, Runtime.exec().

Changer l'extrait de code au motif ci-dessus:

try { 
    ProcessBuilder pb = new ProcessBuilder("/bin/chmod", "777", path);  
    pb.redirectErrorStream(true); // merge stdout, stderr of process 

    Process p = pb.start(); 
    InputStreamReader isr = new InputStreamReader(p.getInputStream()); 
    BufferedReader br = new BufferedReader(isr); 

    String lineRead; 
    while ((lineRead = br.readLine()) != null) { 
     // swallow the line, or print it out - System.out.println(lineRead); 
    } 

    int rc = p.waitFor(); 
    // TODO error handling for non-zero rc 
} 
catch (IOException e) { 
    e.printStackTrace(); // or log it, or otherwise handle it 
} 
catch (InterruptedException ie) { 
    ie.printStackTrace(); // or log it, or otherwise handle it 
} 

(crédit: this site) et voir si cela aide la situation.

+0

Essayé cela, les mêmes exceptions se produisent – Louis

+0

Je pense que je l'ai résolu vérifier ma réponse dans quelques minutes - juste attendre des tests pour vérifier – Louis

+0

Ok ramassé le vôtre comme la réponse comme il le fallait dans la solution , vérifiez mon message inclura les lignes supplémentaires nécessaires. – Louis

0

Il semble peu probable que le processus se termine réellement sans fermer les fichiers. Cela pourrait-il se produire dans un très grand nombre de threads? Ou peut-être que certains d'entre eux ne sont pas en train de terminer (c'est-à-dire qu'ils sont suspendus à waitFor dans certains cas)?

Sinon, je pense que vous serez bloqué avec l'augmentation de la limite de fichiers ouverts. En supposant que c'est un système de type Unix, la commande "ulimit" est probablement ce que vous cherchez.

+0

mis à illimité: \ – Louis

0

Si vous utilisez JAVA 6, vous pouvez également essayer les nouveaux setters (pour lire, écrire, exécuter) sur l'objet File. Peut-être plus lent, mais ça devrait marcher.

6

Merci pour l'aide les gars, cela devrait régler un tas d'étrangeté qui se passe ailleurs à cause de cela.

Utilisation de votre (Vinay) par exemple et les fermetures de flux:

try{ 
    fw.close(); 

    ProcessBuilder pb = new ProcessBuilder("/bin/chmod", "777", path); 

    pb.redirectErrorStream(true); // merge stdout, stderr of process 
    p = pb.start(); 

    InputStreamReader isr = new InputStreamReader(p.getInputStream()); 
    BufferedReader br = new BufferedReader(isr); 

    String lineRead; 
    while ((lineRead = br.readLine()) != null) { 
    // swallow the line, or print it out - System.out.println(lineRead); 
    } 

} catch (Exception ioe) { 
    Logger.logException(Logger.WARN, ioe.getMessage(), ioe); 
} finally { 
    try { 
    p.waitFor();//here as there is some snipped code that was causing a different 
       // exception which stopped it from getting processed 

    //missing these was causing the mass amounts of open 'files' 
    p.getInputStream().close(); 
    p.getOutputStream().close(); 
    p.getErrorStream().close(); 

    } catch (Exception ioe) { 
    Logger.logException(Logger.WARN, ioe.getMessage(), ioe); 
    } 
} 

a eu l'idée de John B Mathews post.

+0

note: n'a toujours pas de sens pourquoi avoir le waitFor et la fermeture des flux d'entrée ne ferait pas très bien mais je suppose que c'est java ... – Louis

+1

Bonne prise, jim, mais je vois encore un problème dans votre 'enfin' . Je pense que vous devez avoir chacun des appels 'close' dans leur propre' catch', sinon si une exception survient quand vous faites 'p.getInputStream.close()', vous ne pourrez pas fermer les autres. Le problème peut sembler avoir disparu maintenant, mais pourrait revenir plus tard. –

+0

bon point. merci – Louis

Questions connexes