From 647d5b243020b799fd7112a801965f5780b86349 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 3 Sep 2019 15:28:32 +0200 Subject: MDEV-20079 When setting back the system time while mysqld is running, NOW() and UNIX_TIMESTAMP() results get stuck typo. system_time.start wasn't updated when system_time.sec and system_time.sec_part were. --- mysql-test/main/system_time_debug.result | 16 ++++++++++++++++ mysql-test/main/system_time_debug.test | 16 ++++++++++++++++ mysys/my_getsystime.c | 2 ++ sql/sql_class.h | 1 + 4 files changed, 35 insertions(+) create mode 100644 mysql-test/main/system_time_debug.result create mode 100644 mysql-test/main/system_time_debug.test diff --git a/mysql-test/main/system_time_debug.result b/mysql-test/main/system_time_debug.result new file mode 100644 index 00000000000..98266f5e9d7 --- /dev/null +++ b/mysql-test/main/system_time_debug.result @@ -0,0 +1,16 @@ +set @old_dbug=@@debug_dbug; +select timestampdiff(minute,now(),sysdate()) as 'must be 0', (unix_timestamp(sysdate()) - unix_timestamp()) div 60 as 'must be 0'; +must be 0 must be 0 +0 0 +set @@debug_dbug='+d,system_time_plus_one_hour'; +select timestampdiff(minute,now(),sysdate()) as 'must be 0', (unix_timestamp(sysdate()) - unix_timestamp()) div 60 as 'must be 0'; +must be 0 must be 0 +0 0 +set @@debug_dbug='+d,system_time_minus_one_hour:-d,system_time_plus_one_hour'; +select timestampdiff(minute,now(),sysdate()) as 'must be 0', (unix_timestamp(sysdate()) - unix_timestamp()) div 60 as 'must be 0'; +must be 0 must be 0 +0 0 +set @@debug_dbug=@old_dbug; +select timestampdiff(minute,now(),sysdate()) as 'must be 0', (unix_timestamp(sysdate()) - unix_timestamp()) div 60 as 'must be 0'; +must be 0 must be 0 +0 0 diff --git a/mysql-test/main/system_time_debug.test b/mysql-test/main/system_time_debug.test new file mode 100644 index 00000000000..040b4c3000e --- /dev/null +++ b/mysql-test/main/system_time_debug.test @@ -0,0 +1,16 @@ +source include/have_debug.inc; +# +# MDEV-20079 When setting back the system time while mysqld is running, NOW() and UNIX_TIMESTAMP() results get stuck +# +set @old_dbug=@@debug_dbug; + +# because NOW() is taken at the beginning of the query and sysdate() is the actual +# time when sysdate() was evaluated, they don't necessarily have to be equal. +# but hopefully they're less than within a minute from each other. +select timestampdiff(minute,now(),sysdate()) as 'must be 0', (unix_timestamp(sysdate()) - unix_timestamp()) div 60 as 'must be 0'; +set @@debug_dbug='+d,system_time_plus_one_hour'; +select timestampdiff(minute,now(),sysdate()) as 'must be 0', (unix_timestamp(sysdate()) - unix_timestamp()) div 60 as 'must be 0'; +set @@debug_dbug='+d,system_time_minus_one_hour:-d,system_time_plus_one_hour'; +select timestampdiff(minute,now(),sysdate()) as 'must be 0', (unix_timestamp(sysdate()) - unix_timestamp()) div 60 as 'must be 0'; +set @@debug_dbug=@old_dbug; +select timestampdiff(minute,now(),sysdate()) as 'must be 0', (unix_timestamp(sysdate()) - unix_timestamp()) div 60 as 'must be 0'; diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c index 677da45ecea..18218c2e8de 100644 --- a/mysys/my_getsystime.c +++ b/mysys/my_getsystime.c @@ -99,6 +99,8 @@ my_hrtime_t my_hrtime() while (gettimeofday(&t, NULL) != 0) {} hrtime.val= t.tv_sec*1000000ULL + t.tv_usec; #endif + DBUG_EXECUTE_IF("system_time_plus_one_hour", hrtime.val += 3600*1000000ULL;); + DBUG_EXECUTE_IF("system_time_minus_one_hour", hrtime.val -= 3600*1000000ULL;); return hrtime; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 3157f19351c..9bd486a540e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3443,6 +3443,7 @@ private: { system_time.sec= sec; system_time.sec_part= sec_part; + system_time.start= hrtime; } else { -- cgit v1.2.1