2009-08-08 7 views
1

Salut, j'ai le code suivant: il utilise otool pour obtenir une liste des bibliothèques partagées utilisées par un binaire alors il utiliseEn utilisant NSTask: congélation app après son retour de sortie

- (IBAction)runTask:(id)sender { 
    NSTask *proc; 
    NSPipe *output; 
    NSData *data; 
    NSString *buffer; 

    proc = [[NSTask alloc] init]; 
    output = [[NSPipe alloc] init]; 

    [proc setLaunchPath:@"/bin/sh"]; 
    [proc setArguments:[NSArray arrayWithObjects: @"-c", @"/usr/bin/otool -L /Applications/TextEdit.app/Contents/MacOS/TextEdit | /usr/bin/awk 'NR>1{print $1}' | /usr/bin/sed -e '/@executable_path/d' -e 's/(.*)$//' -e 's/\\/Versions.*$//'", nil]]; 
    [proc launch]; 

    data = [[output fileHandleForReading] readDataToEndOfFile]; 
    buffer = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; 
    NSLog(@"got: %@", buffer); 

    // Release 
    [proc release]; 
    [output release]; 
    [buffer release]; 
    [data release]; 
} 

Le but de codes est un peu compliqué, sed et awk pour le filtrer dans un format lisible par machine. Juste pour tester j'ai utilisé le binaire de Mac OS X TextEdit.app.

Le problème est que le code s'exécute et renvoie une sortie, mais fige l'application. Je l'ai parcouru ligne par ligne et j'ai trouvé que cette ligne était le problème:

data = [[output fileHandleForReading] readDataToEndOfFile];

Cette ligne enregistre elle-même la sortie sur la console, puis bloque l'application. J'ai vérifié cela en supprimant toutes les autres lignes après cette ligne, et il enregistre toujours la sortie et se fige. Il n'y a rien dans le débogueur et toute suggestion sur la façon de résoudre ce problème serait grandement appréciée.

+1

J'ai copié le code dans un outil de ligne de commande, a ajouté le manque 'setStandardOutput:' message, et il a couru. Cela fonctionne bien, sauf que vous sur-relâchez 'data' à la fin. –

+0

"J'ai vérifié cela en supprimant toutes les autres lignes après cette ligne ..." Je suggère d'échantillonner votre application à la place. Voir l'homme 1 échantillon. –

Répondre

1

La solution à ce problème est simple,

Son un Bug connu qu'après NSTask est exécuté toute exploitation forestière ne fonctionne pas. Il retourne une sortie, c'est juste ne pas l'enregistrer. La solution a été d'ajouter cette ligne:

[task setStandardInput:[NSPipe pipe]]; 

Et tout fonctionne bien :)

2

Il semble que vous manque un

[proc setStandardOutput:output]; 
+0

J'ai ajouté cette ligne mais maintenant il semble que je n'ai pas de sortie du tout. – indragie

0

Vous avez une barre oblique supplémentaire à la fin de la dernière déclaration sed. Une fois que vous l'avez supprimé, le script fonctionne correctement.

+0

Je ne suis pas sûr si j'ai enlevé la barre oblique droite, j'en ai sorti une à la fin de la dernière instruction sed, la ligne ressemble à ceci maintenant [proc setArguments: [NSArray arrayWithObjects: @ "c", @ "/ usr/bin/otool -L /Applications/TextEdit.app/Contents/MacOS/TextEdit | /usr/bin/ awk 'NR> 1 {print $ 1}'// usr/bin/sed -e '/ @ executable_path/d '-e' s /(.*)$// '-e' s/\\/Versions. * $/'", néant]]; Mais je reçois cette erreur: sed: 1: "s/\/Versions. * $/\ N": newline sans échappement à l'intérieur du modèle de remplacement – indragie

+0

Oh, et aussi, je ne pense pas que ce soit un problème avec la commande elle-même , J'ai essayé un très simple "ls/Volumes" et la même chose arrive, la sortie est retournée mais l'application se fige. J'ai ajouté dans la ligne setStandardOutput comme suggéré par l'affiche précédente, et alors que cela résout le problème de congélation, il n'y a plus aucune sortie. Merci – indragie

+0

PCWiz: Ah, j'ai oublié de désappliquer les barres obliques inverses avant d'essayer la commande, et je ne l'ai pas lu pour voir où le dernier motif était supposé se terminer. Cette dernière barre appartient à cet endroit. Pardon. –

0

sortie doit être créé avec [tuyau NSPipe] (unowned) et la sortie doit être définie comme la sortie standard avec [proc setStandardOutput: Sortie]

Mais la raison pour laquelle vous s'écraser est parce que vous publiez des données qui vous n'avez pas alloué, nouveau ou copié. Voir le memory management rules.

Voir aussi Quickies for NSTask pour une implémentation propre et agréable de ce code.

Questions connexes