Utils.c: Fwrite() Returned Error: Broken Pipe How To Solve It ???

Home » Asterisk Users » Utils.c: Fwrite() Returned Error: Broken Pipe How To Solve It ???
Asterisk Users 4 Comments

Dear all,

I want to make call through socket i have set code given below:

#!/usr/bin/perl -w

use IO::Socket::INET;

sub asterisk_command ()
{
# my $command=$_[0];
my
$ami=IO::Socket::INET->new(PeerAddr=>’127.0.0.1′,PeerPort=>5038,Proto=>’tcp’)
or die “failed to connect to AMI!”;
print $ami “Action: Login\r\nUsername: lite\r\nSecret:
4003\r\n\r\nAction: Logoff\r\n\r\n”;
}
&asterisk_command(“Channel: DAHDI/27/7702009896\r\nExten: s\r\nContext:
outbound\r\nCallerID: 20048645\r\nPriority: 1\r\nMaxRetries: 2\r\n”);

Whenever i execute that code i’m get following error

[Oct 10 15:13:23] ERROR[856]: utils.c:1175 ast_careful_fwrite: fwrite()
returned error: Broken pipe
[Oct 10 15:13:23] ERROR[856]: utils.c:1175 ast_careful_fwrite: fwrite()
returned error: Broken pipe
[Oct 10 15:13:23] ERROR[856]: utils.c:1175 ast_careful_fwrite: fwrite()
returned error: Broken pipe
[Oct 10 15:13:23] ERROR[856]: utils.c:1175 ast_careful_fwrite: fwrite()
returned error: Broken pipe

asterisk verison :- 1.6.2.7
CentOS release 5.3
kernel version :- 2.6.18-128.el5

4 thoughts on - Utils.c: Fwrite() Returned Error: Broken Pipe How To Solve It ???

  • In article , akhilesh chand wrote:

    AMI is a *two-way* protocol. You mustn’t just fire in a bunch of commands and close the socket!

    The reason Asterisk reports the fwrite() error is because you have closed the socket before it had a chance to send you the responses.

    What you need to do is this:

    1. Connect to the AMI port.
    2. Read the one-line greeting message that Asterisk sends you. It will tell
    you the version of the protocol (which might be of interest if you wanted
    to be compatible with different versions of Asterisk).
    3. Send the Login action with username, secret and terminating blank line.
    4. Read the response lines from Asterisk until it gives you a blank line.
    5. Send whatever command you want it to do, and go back to step 4.
    6. When you have done the commands you want, send the Logoff action.
    7. *** READ THE RESPONSE TO THE LOGOFF
    8. Close the socket.

    If it helps. Here is similar piece of code I wrote to query pri spans. Note carefully the setting of $/ in two places, and the inclusion of
    “Events: off” to avoid responses getting confused by asynchronous events.

    =================================================================#!/usr/bin/perl

    use IO::Socket;

    my $numspans = 4;
    my $host = ‘localhost’;
    my $login = “Action: login\r\nUsername: xxxx\r\nSecret: yyyy\r\nEvents: off\r\n\r\n”;

    $/ = “\r\n”; # <> reads a single line for signon banner

    my $s = IO::Socket::INET->new(“$host:5038”) or die “can’t connect to $host: $!\n”;
    my $banner = < $s>; # read the banner

    #my $line = (‘-‘ x 78).”\n”;
    #print $banner,$line;

    $/ = “\r\n\r\n”; # <> reads a complete response ending in a blank line

    print $s $login;
    my $resp = < $s>;

    #print $resp,$line;

    my @spans;

    foreach $span (1..$numspans) {
    print $s “Action: Command\r\nCommand: pri show span $span\r\n\r\n”;
    $resp = < $s>;
    #print $resp,$line;

    if ($resp =~ /Status: (.*)\n/) {
    $status = $1;
    } else {
    $status = ‘Unknown’;
    }
    $spans[$span-1] = “Span $span status = $status\n”;
    }

    print $s “Action: Logoff\r\n\r\n”;
    $resp = < $s>;
    #print $resp,$line;

    close $s;

    # go on to display the results from @spans
    =================================================================
    Cheers Tony

  • “Broken Pipe” is a bit misleading because it can refer to other modes of connection besides pipes (although that certainly is the most common case where you would see it). It just means something tried to write to a stream that has already been closed.

    In this case, AMI is trying to send back a response *after* you have already closed the socket. To avoid the error, you need to see if there is any data waiting to be read from the socket, and then read it. (Then, having gone to the trouble of actually reading it, you may as well at least do a simple regular expression match to ensure that what you were expecting to happen actually happened.

    Also, as Asterisk runs on Unix-like systems, you don’t really need the Microsoft-style \r\n line endings. Just an ordinary Unix-style \n on its own will suffice. It even saves a few CPU cycles on the far end (not that you’ll ever actually notice from within an interpreted script).

  • In article <201310101230.56058.asterisk_list@earthshod.co.uk>, A J Stiles wrote:

    Text-based internet protocols (e.g. SMTP, FTP, etc) canonically use \r\n as a line terminator, and AMI does likewise. It may well accept commands with just \n as a line termiator (I haven’t checked), but it certainly sends \r\n to terminate lines that it outputs. IMHO, it’s good to adhere to the same convention in both directions.

    Cheers Tony