Mystery Line in Proc Input in Perl 6
Here's something odd; not sure if it's a bug or just something I don't understand.
I have a utility on my system called k8temp
which reports the temperature of the CPUs. It reports it in Celsius, so I thought I'd write a little wrapper that converts the temps to Fahrenheit. k8temp
outputs one line per core, so on my dual-core system, the output looks like this:
abaugher@bannor> k8temp
CPU 0 Core 0 Sensor 0: 38c
CPU 0 Core 1 Sensor 0: 38c
abaugher@bannor>
And piping it to a hex dump looks like this:
abaugher@bannor> k8temp|hd
00000000: 43 50 55 20, 30 20 43 6f, 72 65 20 30, 20 53 65 6e ;CPU 0 Core 0 Sen
00000010: 73 6f 72 20, 30 3a 20 33, 39 63 0a 43, 50 55 20 30 ;sor 0: 39c.CPU 0
00000020: 20 43 6f 72, 65 20 31 20, 53 65 6e 73, 6f 72 20 30 ; Core 1 Sensor 0
00000030: 3a 20 33 38, 63 0a ;: 38c.
So there are definitely just two lines there, right? But when I run my script, I get three lines: the two expected lines and then a blank one. Here it is:
#!/usr/bin/env perl6
use v6;
sub MAIN() {
my $p = run 'k8temp', :out;
for $p.out.lines {
if / (.*?) (\d+) c / {
say [~] $0, round($1*9/5+32), "°";
} else {
say 'Mystery line: ',$_;
}
}
}
And the output:
abaugher@bannor> ./k8temp.p6
CPU 0 Core 0 Sensor 0: 108°
CPU 0 Core 1 Sensor 0: 106°
Mystery line:
abaugher@bannor> ./k8temp.p6|hd
00000000: 43 50 55 20, 30 20 43 6f, 72 65 20 30, 20 53 65 6e ;CPU 0 Core 0 Sen
00000010: 73 6f 72 20, 30 3a 20 31, 30 39 c2 b0, 0a 43 50 55 ;sor 0: 109°.CPU
00000020: 20 30 20 43, 6f 72 65 20, 31 20 53 65, 6e 73 6f 72 ; 0 Core 1 Sensor
00000030: 20 30 3a 20, 31 30 34 c2, b0 0a 4d 79, 73 74 65 72 ; 0: 104°.Myster
00000040: 79 20 6c 69, 6e 65 3a 20, 0a ;y line: .
So the for
loop is running three times, even though the subprogram only outputs two lines, and the value of $_
the third time through is the empty string. This will require more investigation. Am I missing something obvious here?
Update: I tried a couple things. First, slurping the output of the process shows no third line:
#!/usr/bin/env perl6
use v6;
sub MAIN() {
my $p = run 'k8temp', :out;
print $p.out.slurp-rest;
}
# results
abaugher@bannor> ./k8.p6|hd
00000000: 43 50 55 20, 30 20 43 6f, 72 65 20 30, 20 53 65 6e ;CPU 0 Core 0 Sen
00000010: 73 6f 72 20, 30 3a 20 34, 31 63 0a 43, 50 55 20 30 ;sor 0: 41c.CPU 0
00000020: 20 43 6f 72, 65 20 31 20, 53 65 6e 73, 6f 72 20 30 ; Core 1 Sensor 0
00000030: 3a 20 33 39, 63 0a ;: 39c.
Then using .lines
instead:
#!/usr/bin/env perl6
use v6;
sub MAIN() {
my $p = run 'k8temp', :out;
my @l = $p.out.lines;
@l.perl.say;
}
# results
abaugher@bannor> ./k8.p6
["CPU 0 Core 0 Sensor 0: 42c", "CPU 0 Core 1 Sensor 0: 40c", ""]<>
So .lines()
appears to be adding a third element. Now to figure out why.
Hi Aaron,
I noticed this as well, but I must've forgotten to report a bug for it in RT. I've corrected that mistake: https://rt.perl.org/Ticket/Display.html?id=125796
Please feel free to drop by #perl6 on Freenode and chat with us about your Perl 6 experiences! We can help out with issues like this.
-Rob
It looks like `k8temp` last byte is a "\n" (0x0a).
If lines is implemented as a simple split, this seems to be an expected behavior.
The weird thing is that the docs ( http://docs.perl6.org/type/Str#routine_lines ) seems to say that the ending newline shouldn't add an extra element to the return list
"a\n".lines.elems; # 1
Thanks, Rob. I've been meaning to say hi on #perl6; will do soon.
I notice that if I save the output of k8temp into a file (which does end with a \n), then have my script read from that file with:
my @l = "temps".IO.lines;
@.perl.say;
Then the array only gets two elements, and no extra third with an empty string.
Looking into it, it appears there is a different logic in setting EOF between getting a handle from a file, or from a process. The latter appears to be setting EOF too late, hence the extra empty line.
Determining cause of action now...
Yeah, I tracked both cases to the same line in IO::Handle which calls `nqp::p6box_s(nqp::readlinefh($!PIO)).chomp`, and hadn't figured out yet where to go from there, but I guess it's at the NQP layer.
Tobias Leich went ahead and fixed the bug today!
Cool, I'll have to look and see how; I haven't gotten into the underlying stuff yet.