2009-10-31 6 views
2

C'est bizarre et je ne sais pas vraiment qui est le coupable.FreeBSD, MySQL, Perl, bash: blocage intermittent sur les canaux nommés?

Je fais des scripts, sur FreeBSD (6.2)? qui fait un usage intensif des éléments suivants *** *** bash isme:.

do_something <(mysql --skip-column-names -B -e 'select ... from ... where ...;') 

... où « do_something est un utilitaire peu crufty (en Perl) qui ne sera pas lu à partir d'un pipeline Si je un fichier régulier, il fonctionne très bien. Mon bash scénario utilisant des choses comme exec 4< <(...) avec ces sortes de requêtes (ci-dessous par des boucles de la forme while read x y z <&4; do ... ne semblent jamais avoir des problèmes.

Cependant, Perl (5.8.x) semble bloquer périodiquement (apparemment pour toujours) .J'ai essayé de changer le chomp(my $data = <MYDATA>); avec une routine qui a utilisé sysread et j'ai écrit quelques cas de test en Python pour comparaison. Ceux-ci semblent bloquer beaucoup moins souvent que le code Perl idiomatique, mais ils le font parfois. (Le code Python utilisant f.read() ou os.read(f.fileno()...) semble se comporter à peu près également dans ce numéro).

J'ai essayé de reproduire le problème en utilisant ... <(cat ...) (où je suis cat) et cela ne semble jamais reproduire ce décrochage.

Je l'ai regardé à un ktrace/kdump données ... mais je suis beaucoup plus familier avec Linux strace ou même Solaris fermes ... donc je n'ai pas compris ce qui se passe de là encore, soit. Je suppose que nous pouvons surtout exclure Perl, parce que j'ai reproduit le même problème en utilisant Python ... Je ne vois pas comment le bash pourrait faire quelque chose de mal ici (c'est juste créer un tuyau nommé dans /var/tmp/sh-np-xxx et le câblage des processus jusqu'à ce que).

Que pourrait faire le shell/utilitaire mysql qui pourrait causer cela? Je ne pense pas que je l'ai vu de toute autre chose (comme cat ou dd). Je n'ai pas testé ce scénario sous Linux ... mais j'ai utilisé <(...) (substitution de processus) pendant des années sous Linux et je ne me souviens pas d'avoir jamais vu ça.

Est-ce un problème avec FreeBSD? Bien sûr, je peux contourner le problème en utilisant des fichiers temporaires ... mais je serais sûr de comprendre pourquoi c'est le cas (et d'éviter certaines courses et le désordre de nettoyage que les fichiers temporaires impliquent).

Des suggestions?

Répondre

4

La grande différence entre opérer sur la sortie de mysql et directement sur un fichier est le timing. Lorsque le processus perl est au point mort, la grande question est: "pourquoi ne fait-il pas avancer les choses"? Vous pouvez utiliser l'option "l" pour ps pour voir le canal d'attente pour le processus perl; De cette façon, vous pouvez voir si elle a bloqué sur une lecture, ou si quelque chose d'autre se passe. Si elle est vraiment bloquée sur l'entrée pipe, je m'attends à ce que l'entrée MWCHAN pour perl soit "piperd".

La même information serait intéressante pour le processus mysql.

À quoi ressemble votre code de test Python?

Une autre façon d'écrire ceci tout en évitant le bashisme est ceci: qui vous permettra de excluez bash:

mysql --skip-column-names -B -e 'select ... from ... where ...;' | do_something /dev/stdin 

Autres questions intéressantes:

  • Est-ce que l'option --unbuffered à MySQL changer quoi que ce soit?

  • Est-ce que pipder la sortie mysql via dd change quelque chose? (Par exemple, « PerlScript < (mysql ... | dd)

Résumé:.. Besoin de plus d'informations

+0

Essayé le <(... | chat) et <(... | dd bs = 1) hacks sans aucun changement de comportement, j'essaierai bientôt l'option --unbuffered de mysql Cela semble intrigant et je ne le savais pas auparavant –

+0

La chose vraiment intéressante à découvrir est l'état du mysql et du perl Le test 'dd' sera beaucoup plus intéressant avec un buffer plus grand qu'avec un buffer de petite taille Si vous augmentez la taille du buffer, vous aurez dd manière comme un fichier temporaire mais sans un fichier temporaire – janm

+0

Je vois des problèmes similaires chez solaris qui exécute quelque chose de la forme 'truss -eaf something 2>> (commande pour consommer du texte)'. La chose 'dd bs = 1' n'a pas aidé. 'WCHAN' a juste' '' '. Qu'est-ce qui a fini par le résoudre pour vous? –

Questions connexes