Bug #69044 [Com]: time_sleep_until() starts to early

From: Date: Wed, 02 Oct 2019 15:46:56 +0000
Subject: Bug #69044 [Com]: time_sleep_until() starts to early
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-222991@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 Comment by: phpbugs at canavan dot de Reported by: marc at gutt dot it Summary: time_sleep_until() starts to early 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 behaviour of the following code has changed with this fix. It used to produce different timestamps for the two test files. With the fix for this bug, the timestamps are always the same, which is kind of unexpected. We have worked around this (or implemented this properly, depending on how one sees this) by waiting for fstat($f)['mtime'] on a freshly modified file to change, instead of waiting for time() to change. <?php $f = tmpfile(); $start = time(); print('old time: '.fstat($f)['mtime']. "\n"); fclose($f); /* wait for the next second */ do { } while ($start == time()); $f = tmpfile(); $start = time(); print('new time: '.fstat($f)['mtime']. "\n"); fclose($f); Previous Comments: ------------------------------------------------------------------------ [2019-06-19 07:08:02] krakjoe@php.net 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. ------------------------------------------------------------------------ [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); ?> ------------------------------------------------------------------------ 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 (#222991) next »