Thursday, October 21, 2010

Capturing stdio for a (AGI) Perl process.

I found myself debugging a weird issue the other day with an AGI script that caused me to believe Asterisk::AGI was being confused (as in not doing it properly) about blocking on STDIN for the responses to "GET DATA" requests. Which in turn reminded me that I needed to start capturing a large set of AGI protocol data to write tests around once I have a functioning version of the "Asterisk::MAGI" package I intend on starting soon.

Now multiplexing the input and output of a FileHandle in Perl isn't a difficult thing to accomplish when you have complete control of the FileHandle you want to multiplex. This however is not the case in some (maybe a lot) of Perl packages. They like to do evil things like interacting directly and statically to STDIN, STDOUT, STDERR. Sometimes they even give you the glimmer of hope by allowing you to pass a FileHandle to the constructor or a method but almost willfully ignore the idea of persisting any FileHandle you would like to operate on; spaghetti monster forbid you want to use an "old school" Perl package with a Socket or an IO::Handle object (in memory FileHandles for testing anyone?).

At first when trying to tackle this problem I fooled around with manipulating IO layers using PerlIO (which is neat in it's own right) but found that marshaling read data from an input FileHandle to write's on another FileHandle a bit tricky. It seems that things like the multplexing PerlIO utility layer "tee" worked well on FileHandles being written to (STDOUT) but not for reads. Then, I started hacking around this by trying to insert a "filter" CODE reference hook as a layer for my input FileHandle using PerlIO::code - but this seemed kludgey and a lot of code for a seemingly simple task.

Frustrated and suffering my lack of knowledge regarding PerlIO in general I turned to IRC at which point Matt Trout gave me a perfectly simple and elegant solution to my problem: strace

Why bother with a whole slew of code to do "magic" with FileHandles when I could just trace the system calls for the process in question and capture read and write calls to the file descriptors in question.

The result was this little snippet that I modified from his example:

Which will take input like this:

And gives you this:

Since the whole point of this little exercise was to allow me to capture a lot of IO data between Asterisk and a   Perl AGI script I decided that a system() call to strace would be good as calling strace from a dialplan is a bit of a pain:

Just do the above in a BEGIN block and you are set as the -s flag tells strace to keep a large string buffer and the -ff option tells strace to name it's -o output file by pid.

1 comment:

  1. Make sure to set aside sure amount|a specific amount|a certain quantity} that you're willing to lose, and by no means gamble with money you can't afford to lose. This will help {ensure that|make sure that|be sure that} you don’t go overboard whereas taking part in} and end up in debt. It is also be|can be} necessary to bear in 온라인 카지노 mind the payout proportion of the games you’re taking part in}. Wagering on games with a high payout proportion provides gamers a better chance of winning in lengthy run|the lengthy term} when in comparison with} games with lower payouts.