http://qs321.pair.com?node_id=1195620


in reply to Re: sysread() is deprecated on :utf8 handles
in thread sysread() is deprecated on :utf8 handles

I appreciate that Laurent_R but the code cannot use buffered IO as it is using IO::Select which is why the code was changed to use sysread many years ago (apparently). sysread did/does support :utf8 although I realise it is unvalidated UTF-8.

The problem I am seeking an answer to is how to continue using sysread without getting the deprecated warnings OR how to change the code to use some other unbuffered read that supports UTF8 layer.

So far I have tried changing the layer on the read end of the socket to :unix (instead of UTF-8), reading the bytes and decoding them. This appears to work but has the caveate that if a part message was read the octets in it might fall in the middle of a UTF8 character.

Replies are listed 'Best First'.
Re^3: sysread() is deprecated on :utf8 handles
by thanos1983 (Parson) on Jul 20, 2017 at 15:36 UTC

    Hello again mje,

    Did you try the module that I recommend earlier?

    Regarding your question The problem I am seeking an answer to is how to continue using sysread without getting the deprecated warnings I do not recommend that but you can read more here Supressing warnings.

    Let us know what you have tried so far, provide us a sample of code to replicate the problem. We are just guessing for the moment.

    Hope this helps, BR

    Seeking for Perl wisdom...on the process of learning...not there...yet!

      I did not try File::Slurper because I am not slurping a file, I'm reading data from a socket.

      I don't want to suppress the warning since it is warning of a deprecation which implies it will break in the future.

      There is a parent and a forked child process. The child creates a socket and starts listening for connections using IO::Select to see when the socket is read ready. The parent connects to the child's socket, sets encoding(UTF-8) and sends UTF-8 encoded XML down the socket to the child. The child sees the parents connect, accepts it enables encoding(UTF-8) on the new socket. When the child sees data, it reads it with sysread. There is a bit more to it than that but that is the essence of it.

      The code is like (but not exactly) this

      use 5.016; use strict; use warnings; use Socket; use IO::Socket; use IO::Socket::INET; use Data::Dumper; use IO::Select; use Errno qw(EPIPE); my $port = '11111'; my $pid = fork; if ($pid) { # server sleep 10; my $sock1; my $attempts = 100; while ($attempts--) { $sock1 = IO::Socket::INET->new ( PeerHost => 'localhost', PeerPort => '9001', Proto => 'tcp'); if (!$sock1) { say "Cannot connect to child socket - $!"; sleep 2; } else { last; } } if (!$sock1) { say "Failed to connect after 100 attempts"; say "Killing child"; kill 'TERM', $pid; say "waiting on child"; waitpid($pid, 0); } binmode($sock1, ':encoding(UTF-8)'); $sock1->send("<element>Hello</element>\r\n"); sleep 10; my $sock2 = IO::Socket::INET->new ( PeerHost => 'localhost', PeerPort => '9001', Proto => 'tcp'); $sock2->send("<element>Hello2</element>\r\n"); sleep 10; say "shutdown 1"; shutdown($sock1, 1); # stopped writing shutdown($sock2, 1); # stopped writing sleep 5; say "shutdown 2"; shutdown($sock1, 2); # stopped using this socket shutdown($sock2, 2); # stopped using this socket sleep 5; say "closing socket"; close($sock1); close($sock2); say "Killing child"; kill 'TERM', $pid; say "waiting on child"; waitpid($pid, 0); say "parent exiting"; exit; } elsif (!defined $pid) { die "fork failed with $!"; } else { # child say "child started"; sleep 15; my $sock = IO::Socket::INET->new(Listen => 50, LocalAddr => 'localhost', LocalPort => 9001, Proto => 'tcp', ReuseAddr => 1); my $select = IO::Select->new(); $select->add($sock); my $buf = ''; while (1) { #exit 0; uncomment to test SIGPIPE my @ready = $select->can_read(5); foreach my $ready (@ready) { if ($ready == $sock) { my $s = $sock->accept(); my $client_address = $s->peerhost(); my $client_port = $s->peerport(); say "connection from $client_address:$client_port\n"; $select->add($s); binmode($s, ':encoding(UTF-8)'); } else { say "Child reading socket"; my $read = sysread($ready, $buf, 1024, length($buf)); if (!defined($read)) { say "Child sysread error - $!"; last; } elsif ($read == 0) { say "Child EOF"; $select->remove($ready); close $ready; sleep 1; last; } else { while ($buf =~ s/^(.*)\r\n//) { say "Child got /$1/"; # child does something with this }; } } } } exit; }

      Results in

      child started Cannot connect to child socket - Connection refused Cannot connect to child socket - Connection refused Cannot connect to child socket - Connection refused connection from 127.0.0.1:39310 Child reading socket Child got /<element>Hello</element>/ connection from 127.0.0.1:39318 Child reading socket Child got /<element>Hello2</element>/ shutdown 1 Child reading socket Child EOF Child reading socket Child EOF shutdown 2 closing socket Killing child waiting on child parent exiting

        Hello mje,

        You can use read as a temporary solution it does not give the warning, but it is not the same as sysread.

        From the read documentation:

        The call is implemented in terms of either Perl's or your system's native fread(3) library function. To get a true read(2) system call, see sysread.

        I just tested with your code and the output looks ok:

        $ perl test.pl child started Cannot connect to child socket - Connection refused Cannot connect to child socket - Connection refused Cannot connect to child socket - Connection refused connection from 127.0.0.1:33980 Child reading socket shutdown 1 Child got /<element>Hello</element>/ connection from 127.0.0.1:33982 Child reading socket Child EOF Child reading socket Child got /<element>Hello2</element>/ Child reading socket Child EOF shutdown 2 closing socket Killing child waiting on child parent exiting

        In comparison with sysread:

        $ perl test.pl child started Cannot connect to child socket - Connection refused Cannot connect to child socket - Connection refused Cannot connect to child socket - Connection refused connection from 127.0.0.1:33788 Child reading socket sysread() is deprecated on :utf8 handles at test.pl line 108. Child got /<element>Hello</element>/ connection from 127.0.0.1:33792 Child reading socket sysread() is deprecated on :utf8 handles at test.pl line 108. Child got /<element>Hello2</element>/ shutdown 1 Child reading socket sysread() is deprecated on :utf8 handles at test.pl line 108. Child EOF Child reading socket sysread() is deprecated on :utf8 handles at test.pl line 108. Child EOF shutdown 2 closing socket Killing child waiting on child parent exiting

        Give it a try if it meets your criteria.

        I tested on:

        $ perl -v This is perl 5, version 24, subversion 1 (v5.24.1) built for x86_64-li +nux-gnu-thread-multi (with 67 registered patches, see perl -V for more detail) Copyright 1987-2017, Larry Wall Perl may be copied only under the terms of either the Artistic License + or the GNU General Public License, which may be found in the Perl 5 source ki +t. Complete documentation for Perl, including FAQ lists, should be found +on this system using "man perl" or "perldoc perl". If you have access to + the Internet, point your browser at http://www.perl.org/, the Perl Home Pa +ge.

        Hope this helps, BR.

        Seeking for Perl wisdom...on the process of learning...not there...yet!