jonathanstowe / TermReadKey

Character mode terminal access for Perl
12 stars 27 forks source link

"ReadKey" deadlocks with latest StrawberryPerl #25

Closed amba closed 7 years ago

amba commented 7 years ago

If you give ReadKey an argument between 0 and 1, it hangs forever.

This was working fine with StrawberryPerl 5.20.1.1.

Code:

use 5.020;
use warnings;
use strict;

use Term::ReadKey;

warn "Version: $Term::ReadKey::VERSION \n";

my $x = ReadKey(1e-5);

warn "x: $x";

You can reproduce this easily, even without a windows installation, using the following Appveyor build script: (See a recent blog post of eserte)

install:
  - choco install strawberryperl
  - path C:\strawberry\perl\bin;C:\strawberry\perl\site\bin;C:\strawberry\c\bin;%PATH%
  - perl -V

build_script:
  - perl term-readkey.pl

See https://ci.appveyor.com/project/amba/term-readkey-windows/build/1.0.3 for the full build log.

jonathanstowe commented 7 years ago

I can't easily fix it without a windows installation, this does look somewhat like a bug in StrawberryPerl.

I think the best I will be able to do is treat 0 > $ < 1 as 1

amba commented 7 years ago

I've opened a StrawberryPerl bug: https://rt.cpan.org/Public/Bug/Display.html?id=120043

jonathanstowe commented 7 years ago

It may be useful if you could paste the generated verision of the ReadKey from the installed ReadKey.pm as it's not clear which one would be used with SP :)

amba commented 7 years ago

The Strawberry Perl upstream's response to my report:

On a MSWin32 ReadKey function looks like this:

sub ReadKey { my $File = normalizehandle((@>1?$[1]:*STDIN)); if ($[0] || $CurrentMode >= 3) { Win32PeekChar($File, $[0]); } else { getc $File; } }

where Win32PeekChar looks like this:

SV * Win32PeekChar(file, delay) InputStream file U32 delay <<<<<<<<<<<<<<<<< the trouble!!! CODE: { char key; if (Win32PeekChar(aTHX_ file, delay, &key)) RETVAL = newSVpv(&key, 1); else RETVAL = newSVsv(&PL_sv_undef); } OUTPUT: RETVAL

So calling something like this:

my $x = ReadKey(1e-5);

means that the delay value 1e-5 is converted to U32 (unsigned 32bit integer) which I guess would be 0 (zero), therefore the same as calling my $x = ReadKey(0) - which is exactly what it does (blocking read waiting till you hit any key).

As for the versions:

  • Strawberry Perl 5.20.1.1 has TermReadKey-2.31
  • Strawberry Perl 5.24.1.1 has TermReadKey-2.37

And if you compare 2.31 vs. 2.37 you will find:

-int Win32PeekChar(PerlIO file,double delay,char key) +int Win32PeekChar(pTHX_ PerlIO file,U32 delay,char key)

Note "double delay" vs. "U32 delay"

Full diff: https://metacpan.org/diff/file?target=JSTOWE%2FTermReadKey-2.37%2F&amp;source=JSTOWE%2FTermReadKey-2.31

So IMHO definitely not a bug Strawberry Perl. ReadKey's Win32PeekChar needs a fix.

jonathanstowe commented 7 years ago

I'll need to check why that was changed like that in the first place.

amba commented 7 years ago

Thanks for the merge!