[TriLUG] help with Perl TCP server

Wes Garrison via TriLUG trilug at trilug.org
Tue Aug 30 12:15:48 EDT 2016


Hi folks,

I need help with a Perl TCP server that I have listening for small JSON
messages.

It keeps "crashing" with the messages:
Use of uninitialized value in subroutine entry at
/usr/lib/x86_64-linux-gnu/perl/5.20/Socket.pm line 153.
Bad arg length for Socket::unpack_sockaddr_in, length is 0, should be 16 at
/usr/lib/x86_64-linux-gnu/perl/5.20/Socket.pm line 153.

(it's running as a daemon in Debian so it's not really "crashing", but the
service is stopping with a status of "active (exited)" every day or 2)

I am using the Perl TCP server from the Perl Cookbook
<http://docstore.mik.ua/orelly/perl3/cookbook/ch17_03.htm> with minimal
modification, so I'm not sure what is causing this.

It *looks *like $sock->peername is sometimes returning 0 or an undefined
value, but that shouldn't cause the whole service to die.
Line 153 of Socket.pm is:
 elsif (wantarray) {
        croak "usage:   (port,iaddr) = sockaddr_in(sin_sv)" unless @_ == 1;
        unpack_sockaddr_in(@_); ### line 153
    }

The only references I can find to this error message are for a Perl bug
report for AmigaOS, which doesn't seem to apply here:
http://www.perlmonks.org/?node_id=1141502
https://rt.cpan.org/Public/Bug/Display.html?id=106797

I've been fighting with this for a while and I'm at a loss.

I've attached a stripped-down version of the server in case that helps.  (I
changed the file extension to .txt so malware filters won't flag it.)

Any insights would be greatly appreciated!

-Wes
_________________________________
Wesley S. Garrison
Network Engineer
Xitech Communications, Inc.
phone:  (919) 260-0803
fax:       (919) 932-5051
__________________________________
"Lead us not into temptation, but deliver us from email."
-------------- next part --------------
#!/usr/bin/perl -w
use strict;
use warnings;
use IO::Socket;
use DBI;
use JSON -support_by_pp;
 
my $dieNow        = 0;                                     # used for "infinte loop" construct - allows daemon mode to gracefully exit
my $sleepMainLoop = 1;                                    # number of seconds to wait between "do something" execution after queue is clear

until ($dieNow) {
	sleep($sleepMainLoop);
 
	my($server_socket, $sock, $oldmsg, $newmsg, $hisaddr, $hishost, $MAXLEN, $PORTNO, $currentPoll);
	$MAXLEN = 1024;
	$PORTNO = 8531;
	
	$| = 1; ## auto flush on socket
	$server_socket = IO::Socket::INET->new(
	LocalHost => '0.0.0.0',
	LocalPort => $PORTNO,
	Proto => 'tcp',
	Listen => 5,
	Reuse => 1
	) or die "socket: $@";

	logEntry ("Awaiting TCP messages on port $PORTNO");
	
	while ($sock = $server_socket->accept()) {
		
		#### I put this check in to make sure the socket exists before I called $sock->peername or inet_ntoa($ipaddr)
		#### but maybe it's not necessary?
		if ($sock) {
			$sock->recv($newmsg, $MAXLEN);
		}
		else {
			next;
		}
		#########################################################

		my($port, $ipaddr) = sockaddr_in($sock->peername);
		$hishost = inet_ntoa($ipaddr);
		
		logEntry ($hishost ." said ". $newmsg);  ### debugging

		if (!($newmsg =~ /}/)) {
			(my $ICCID, $currentPoll, my $RSSI) = split(/,/,$newmsg);
			if (length($ICCID) == 20) {
				$newmsg = '{"msg":"get","ICCID":"'.$ICCID.'","RSSI":'.$RSSI.'}';	
			}
		}

		eval {
			my $json = new JSON;
			$newmsg = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->decode($newmsg);		
			return 1;
		}	or do {
			logEntry ("Bad JSON, $hishost said ".$newmsg);
			$sock->send('{"error":"Bad JSON format!"}');
			shutdown($sock, 1);
			next;
		};

		#########################################################################
		### Make Database Calls and stuff here
		#########################################################################

		shutdown($sock, 1);

	} ### end while $sock is receiving data

	logEntry ("recv: $!");
	close($server_socket);

} ### end until receive $dieNow from service


More information about the TriLUG mailing list