Subject: | Time::NVtime pointer mis-documented or mis-implemented |
Time::HiRes documents the Time::NVtime as returning double, per:
name C prototype
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(pTHX_ UV ret[2])
and the examples:
double (*myNVtime)(); /* Returns -1 on failure. */
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
but it is actually implemented as returning an NV, which on -Duselongdouble builds is a long double.
On Linux x86_64, doubles are returned on the FPU stack, while long doubles are returned in memory, as with structures.
Code that uses the documentation (eg. Time::Warp, Coro) ends up either underflowing the FPU stack or leaving trash on the FPU stack, which after multiple calls can result in an FPU stack overflow.
This can be hard to track down.
See https://rt.perl.org/Ticket/Display.html?id=123879 for an example of the failure.
Either the documentation needs to be corrected to use the NV return value, or the implementation needs to use double.
Either way, some CPAN modules will need fixes, Time::Warp and Coro use the double type, Event and (to my surprise) my POE::XS::Loop::Poll use the NV prototype.
Thanks
Tony