当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 14 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 13:06 

注册: 2013-05-26 6:58
帖子: 2154
系统: Debian 9
送出感谢: 893
接收感谢: 30
ntpdate貌似有个Bug,但源代码里看不出来?
测试前请注意当前系统时间正确与否是否重要
因为调整系统时间之后很可能出现服务器不可用的情况
遇到这种情况一般可以想办法换个IP去同步
比如我这里PPP方式联网就是断开重连
如果系统时间和服务器时间偏差太大导致此Bug被触发
可以添加"-b"参数来强制使用step(步进)方式同步

触发Bug的命令:
代码:
date -s @$((`date +%s` +100000)); ./ntpdate  -p 1 cn.pool.ntp.org

但代码逻辑上貌似没有问题?
ntpdate.c代码:
代码:
   if (always_step) {
      dostep = 1;
   } else if (never_step) {
      dostep = 0;
   } else {
      absoffset = server->soffset;
      if (absoffset < 0)
         absoffset = -absoffset;

         //由于前面的if,absoffset应该不可能是负数,但是我加上这段调试代码输出却发现absoffset是负数
         //absoffset为负数后就导致了dostep变量的数值异常,结果该"step"(步进)时却进行"adjust"(微调)了
         //absoffset的类型应该也没弄错,是int32,应该就是用%d输出吧?
         //msyslog这个函数我也没弄明白,只是照着printf猜的用法
         //但从ntpdate的外部行为推测,dostep变量确实发生了异常
         msyslog(LOG_NOTICE, "absoffset: %d \n NTPDATE_THRESHOLD :%d",absoffset,NTPDATE_THRESHOLD);
      dostep = (absoffset >= NTPDATE_THRESHOLD || absoffset < 0);
   }

   if (dostep) {
      if (simple_query || debug || l_step_systime(&server->offset)){
         msyslog(LOG_NOTICE, "step time server %s offset %s sec",
            stoa(&server->srcadr),
            lfptoa(&server->offset, 6));
      }
   } else {
#ifndef SYS_WINNT
      if (simple_query || l_adj_systime(&server->offset)) {
         msyslog(LOG_NOTICE, "adjust time server %s offset %s sec",
            stoa(&server->srcadr),
            lfptoa(&server->offset, 6));
      }


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


最后由 科学之子 编辑于 2016-08-19 23:52,总共编辑了 1 次

页首
 用户资料  
 
2 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 14:00 

注册: 2013-05-26 6:58
帖子: 2154
系统: Debian 9
送出感谢: 893
接收感谢: 30
下面是命令+输出
代码:
# date -s @$((`date +%s` +100000)); ./ntpdate  -p 1 cn.pool.ntp.org
Sat Aug 20 17:45:52 CST 2016
20 Aug 17:45:52 ntpdate[4964]: absoffset: -2147483648
 NTPDATE_THRESHOLD :32768
20 Aug 17:45:52 ntpdate[4964]: Can't adjust the time of day: Invalid argument


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
3 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 14:25 
头像

注册: 2011-03-20 13:12
帖子: 4520
地址: 山东省寿光县
系统: Debian
送出感谢: 105
接收感谢: 997
或为 http://bugs.ntp.org/show_bug.cgi?id=3023

貌似已于 ntp 4.2.8p7 修复。在 stretch/sid (4.2.8p8) 中是否仍有此问题有待测试。
https://fossies.org/diffs/ntp/4.2.8p6_vs_4.2.8p7/ntpdate/ntpdate.c-diff.html

看来此处问题多多,早在 2002 年就有类似问题:
http://marc.info/?l=ntp-bugs&m=103224904812746&w=2


_________________
Debian 中文论坛 - forums.debiancn.org
欢迎所有 Debian GNU/Linux 用户



_________________
评价: 3.7% 科学之子
 
页首
 用户资料  
 
4 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 17:12 

注册: 2013-05-26 6:58
帖子: 2154
系统: Debian 9
送出感谢: 893
接收感谢: 30
vickycq 写道:
或为 http://bugs.ntp.org/show_bug.cgi?id=3023

貌似已于 ntp 4.2.8p7 修复。在 stretch/sid (4.2.8p8) 中是否仍有此问题有待测试。
https://fossies.org/diffs/ntp/4.2.8p6_vs_4.2.8p7/ntpdate/ntpdate.c-diff.html

看来此处问题多多,早在 2002 年就有类似问题:
http://marc.info/?l=ntp-bugs&m=103224904812746&w=2

代码:
/* [Bug 3023] get absolute difference, avoiding signed
 * integer overflow like hell.
 */

改为无符号就能解决了吗?
问题是就算是有符号溢出了,按理说那个if也能保证不会出现负数啊
为什么运行过程就出现负数了呢?
难道是"Memory barrier"之类的原因?(只是知道那么个名词和抽象的定义,但具体是如何作用的还是不明白)
不过我还是看不透...


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
5 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 19:45 
头像

注册: 2008-09-18 13:11
帖子: 2781
送出感谢: 1
接收感谢: 453
不就是一个典型的整型溢出嘛
代码:
#include <stdio.h>
int main() {
    int a = 0x80000000;
    printf("%d %d\n", a, -a);
    return 0;
}



_________________
评价: 3.7% 科学之子
 
页首
 用户资料  
 
6 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 19:54 

注册: 2013-05-26 6:58
帖子: 2154
系统: Debian 9
送出感谢: 893
接收感谢: 30
astolia 写道:
不就是一个典型的整型溢出嘛
代码:
#include <stdio.h>
int main() {
    int a = 0x80000000;
    printf("%d %d\n", a, -a);
    return 0;
}

但是前面有个if取绝对值
代码:
if (absoffset < 0)
         absoffset = -absoffset;

按理就算溢出了也不应该出现负数?
到了计算dostep时,absoffset应该永远都是>=0
当然,以上仅教科书式判断,实际情况我就不清楚为什么异常了.
Fri Aug 19 19:56:47 CST 2016补充:
:Aadterboom
刚刚试了下,居然还有无法取反数的整型值?
这就是传说中的负0的实现?


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
7 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 20:16 
头像

注册: 2008-09-18 13:11
帖子: 2781
送出感谢: 1
接收感谢: 453
这是任何计算机专业大一一进去就要学的计算机组成原理的内容之一:有符号整数的表示方式。一般会放在第二章,在第一章绪论之后
你可以看这篇,看到第四段就明白了 http://www.it610.com/article/414917.htm
至于负0,那是浮点数的内容,组成原理那一章同样会讲。自己找本书来看看就知道了



_________________
评价: 7.41% vickycq科学之子
 
页首
 用户资料  
 
8 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 20:30 

注册: 2013-05-26 6:58
帖子: 2154
系统: Debian 9
送出感谢: 893
接收感谢: 30
astolia 写道:
这是任何计算机专业大一一进去就要学的计算机组成原理的内容之一:有符号整数的表示方式。一般会放在第二章,在第一章绪论之后
你可以看这篇,看到第四段就明白了 http://www.it610.com/article/414917.htm
至于负0,那是浮点数的内容,组成原理那一章同样会讲。自己找本书来看看就知道了


我记得某个教程(忘了是什么了)说过虽然补码的0表示是唯一的,但整型的二进制"负0"的形式会因为平台不同而有不同实现
感谢纠正

不过就算是INT_MIN,后面那个逻辑或也应该是结果为True?
代码:
#include <stdio.h>
#include <limits.h>
int main() {
   int dostep=0;
    int a = 0x80000000;
    if(a<0)a=-a;
   
    dostep = (a >= INT_MAX || a < 0);
    //dostep输出非0值
    printf("%d\n",dostep);
    printf("%d %d\n", a, -a);
    printf("%d\n",INT_MIN);
    unsigned i=0;
    for(i=0;i<sizeof(a);i++)
    printf("%.2x\n",((unsigned char*)(&a))[i]);
    return 0;
}


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
9 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 20:48 

注册: 2013-05-26 6:58
帖子: 2154
系统: Debian 9
送出感谢: 893
接收感谢: 30
照着nptdate里面那个宏展手动开了一下
结果还是输出非0值
代码:
#include <stdio.h>
#include <limits.h>
int main() {
   int dostep=0;
    int a = 0x80000000;
    int b = INT_MIN;
    if(a<0)a=-a;
   
    dostep = (b >= ((0x10000) >> 1) || b < 0);
    //dostep输出非0值
    printf("%d\n",dostep);
    printf("%d %d\n", a, -a);
    printf("%d %d\n",b ,-b);
    unsigned i=0;
    for(i=0;i<sizeof(a);i++)
    printf("%.2x\n",((unsigned char*)(&a))[i]);
    return 0;
}


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
10 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 21:09 
头像

注册: 2008-09-18 13:11
帖子: 2781
送出感谢: 1
接收感谢: 453
科学之子 写道:
整型的二进制"负0"的形式会因为平台不同而有不同实现

这个平台是指处理器,根据这篇 https://en.wikipedia.org/wiki/Two%27s_complement 的说法,支持两种符号整数0的小型/微型机在1970年之后就基本绝迹了。所以现在只存在只有正整数0的平台。

我不明白你拿那段代码想说啥。 a == 0x80000000 == b == INT_MIN == -2147483648,-2147483648<0为真,dostep也就为真,即1,有什么奇怪的?
你该不是把shell脚本里的0为真和C里面的非零为真弄混了吧



_________________
评价: 3.7% 科学之子
 
页首
 用户资料  
 
11 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 22:55 

注册: 2013-05-26 6:58
帖子: 2154
系统: Debian 9
送出感谢: 893
接收感谢: 30
astolia 写道:
科学之子 写道:
整型的二进制"负0"的形式会因为平台不同而有不同实现

这个平台是指处理器,根据这篇 https://en.wikipedia.org/wiki/Two%27s_complement 的说法,支持两种符号整数0的小型/微型机在1970年之后就基本绝迹了。所以现在只存在只有正整数0的平台。

我不明白你拿那段代码想说啥。 a == 0x80000000 == b == INT_MIN == -2147483648,-2147483648<0为真,dostep也就为真,即1,有什么奇怪的?
你该不是把shell脚本里的0为真和C里面的非零为真弄混了吧

但是dostep为1的话,就应该是step(步进)而非adjust(微调)
我发那个代码就是想说明,ntpdate的表现和我发的代码的表现不同
我无法看出这是什么原因


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
12 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 23:38 

注册: 2013-05-26 6:58
帖子: 2154
系统: Debian 9
送出感谢: 893
接收感谢: 30
好奇怪,一输出dostep值,程序就正常
不输出就好像dostep异常了一样,表现出错误行为
加上注释就出现那个Bug,去掉注释,输出dostep的值就正常了
代码:
//msyslog(LOG_NOTICE, "\ndostep:%d\n",dostep);
   if (dostep) {
      if (simple_query || debug || l_step_systime(&server->offset)){
         msyslog(LOG_NOTICE, "step time server %s offset %s sec",
            stoa(&server->srcadr),
            lfptoa(&server->offset, 6));
      }
   }


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
13 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-19 23:47 
头像

注册: 2008-09-18 13:11
帖子: 2781
送出感谢: 1
接收感谢: 453
引用:
但是dostep为1的话,就应该是step(步进)而非adjust(微调)

我知道你的想法了:看到报错信息是Can't adjust the time of day,在源码里搜了一下,发现是个l_adj_systime函数输出的,再从头搜一下,看到了一楼的代码段,发现是当dostep为0时调用的,加了点调试语句,结果dostep值为1,然后就懵了
我说你咋就不去看一眼l_step_systime()的实现呢?



_________________
评价: 3.7% 科学之子
 
页首
 用户资料  
 
14 楼 
 文章标题 : Re: ntpdate貌似有个Bug,但源代码里看不出来?
帖子发表于 : 2016-08-20 21:55 

注册: 2013-05-26 6:58
帖子: 2154
系统: Debian 9
送出感谢: 893
接收感谢: 30
astolia 写道:
引用:
但是dostep为1的话,就应该是step(步进)而非adjust(微调)

我知道你的想法了:看到报错信息是Can't adjust the time of day,在源码里搜了一下,发现是个l_adj_systime函数输出的,再从头搜一下,看到了一楼的代码段,发现是当dostep为0时调用的,加了点调试语句,结果dostep值为1,然后就懵了
我说你咋就不去看一眼l_step_systime()的实现呢?

确实没看.
不过为什么要看l_step_systime()的实现?
仔细看了一下,里面会调用l_adj_systime(而且貌似是在有特殊的宏定义时才调用)
但问题在于症状是l_step_systime()根本没有被调用.
虽然代码逻辑上确实应该被调用

我在l_step_systime()的第一行加上"fprintf(stderr,"正常\n");",它也没输出

奇怪的是如果clock_adjust里面在那个if上面加上输出代码,就会改变结果到正常结果

代码:
//如果没有这个输出语句,就会调用adjust
//这个输出语句的存在使程序的行为变正常了,不知道为什么
fprintf(stderr,"dostep:%d\n",dostep);

   if (dostep) {


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 14 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 1 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译