Bug #69044 [Asn->Csd]: time_sleep_until() starts to early

From: Date: Wed, 19 Jun 2019 07:08:02 +0000
Subject: Bug #69044 [Asn->Csd]: time_sleep_until() starts to early
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-221378@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69044&edit=1 ID: 69044 Updated by: krakjoe@php.net Reported by: marc at gutt dot it Summary: time_sleep_until() starts to early -Status: Assigned +Status: Closed Type: Bug Package: Date/time related Operating System: Debian PHP Version: 5.4.37 Assigned To: selim61 Block user comment: N Private report: N New Comment: The fix for this bug has been committed. Snapshots of the sources are packaged every three hours; this change will be in the next snapshot. You can grab the snapshot at http://snaps.php.net/. For Windows: http://windows.php.net/snapshots/ Thank you for the report, and for helping us make PHP better. Previous Comments: ------------------------------------------------------------------------ [2019-06-17 13:57:41] nikic@php.net Here is the reason for the discrepancy: https://stackoverflow.com/questions/22917318/time-and-gettimeofday-return-different-seconds TLDR We use two different APIs for time() and microtime() and the latter is not just more precise when it comes to sub-second resolution, it also calculates the seconds more precisely. ------------------------------------------------------------------------ [2015-02-14 13:32:55] marc at gutt dot it Yes, date() seems to have a bug: <?php function udate($format, $timestamp=null) { if (!isset($timestamp)) $timestamp = microtime(); // microtime(true) if (count($t = explode(" ", $timestamp)) == 1) { list($timestamp, $usec) = explode(".", $timestamp); $usec = "." . $usec; } // microtime() is more precise else { $usec = $t[0]; $timestamp = $t[1]; } // 7 decimal places for "u" is maximum $usec = substr(sprintf('%.7f', $usec), 1); $date = new DateTime(date('Y-m-d H:i:s' . $usec, $timestamp)); return $date->format($format); } echo "### first test ###\n"; $sleep_until = round(microtime(true)) + 3.002; echo "sleep: " . udate("Y-m-d\TH:i:s.u", $sleep_until) . "\n"; time_sleep_until($sleep_until); echo "udate: " . udate("Y-m-d\TH:i:s.u", microtime(true)) . "\n"; echo "date : " . date("Y-m-d\TH:i:s") . "\n"; echo "### second test ###\n"; $sleep_until = round(microtime(true)) + 3.003; echo "sleep: " . udate("Y-m-d\TH:i:s.u", $sleep_until) . "\n"; time_sleep_until($sleep_until); echo "udate: " . udate("Y-m-d\TH:i:s.u", microtime(true)) . "\n"; echo "date : " . date("Y-m-d\TH:i:s") . "\n"; /* results: ### first test ### sleep: 2015-02-14T14:29:51.002000 udate: 2015-02-14T14:29:51.002100 date : 2015-02-14T14:29:50 ### second test ### sleep: 2015-02-14T14:29:54.003000 udate: 2015-02-14T14:29:54.003100 date : 2015-02-14T14:29:54 */ ?> ------------------------------------------------------------------------ [2015-02-14 02:00:02] requinix@php.net By the way, the code works fine on Windows: time() - $sleep_until = 0 consistently. Tried the same code on Ubuntu 14.04 and would get -1 consistently. ------------------------------------------------------------------------ [2015-02-14 01:44:44] yohgaki@php.net You can see it's sleeping as it supposed by replacing date() to microtime() <?php $sleep_until = microtime(true) + 1; echo "sleep until " . $sleep_until ."\n"; time_sleep_until($sleep_until); echo "woke up at " . microtime(true); ?> ------------------------------------------------------------------------ [2015-02-14 01:39:34] yohgaki@php.net My previous analysis is wrong. time_sleep_until() sleeps as it supposed. It seems date() is doing something wrong. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=69044 -- Edit this bug report at https://bugs.php.net/bug.php?id=69044&edit=1

« previous php.bugs (#221378) next »