继续收集Internet上有关错误有时是如何完全令人难以置信的表现的故事。第一部分在这里。
更神奇
几年前,我在麻省理工学院AI实验室的PDP-10计算机的壁橱里翻腾。我注意到一个小开关粘在一个柜子的框架上。显然,它是一种自制产品,是由一名实验室工匠添加的(没人知道谁是谁)。
在不知道其功能的情况下,您不会触摸计算机上的未知开关,因为这可能会损坏计算机。开关完全无法理解。它有两个位置,用铅笔在金属机身上写了“魔术”和“更多魔术”两个字。开关处于更神奇的位置。我打电话给其中一位技术员看一下。他以前从未见过。经过仔细检查,结果发现只有一根电线连接到了交换机!电线的另一端消失在计算机内部的电缆杂乱中,但是电的性质决定了直到您将两根电线插入其中后,交换机才能做任何事情。
很明显,这是一个愚蠢的笑话。确保开关不执行任何操作后,我们将其切换。电脑立即消失了。
想象一下我们的惊奇。我们将其归为巧合,但是在启动计算机之前,仍将按钮重新置于“更具魔力”的位置。
一年后,据我所记得,我曾向另一位技术员David Moon讲过这个故事。他质疑我是否足够,或者怀疑自己相信这种转换的超自然性,或者以为我在骗他的假话。为了证明我的观点,我向他展示了此开关,该开关仍粘在框架上,并用单根电线仍处于“更神奇”的位置。我们仔细检查了开关和电线,发现其已接地。它看起来没有任何意义,它不仅没有电,而且插在不影响任何东西的地方。我们将其移至其他位置。
电脑立即变成空白。
我们与附近的MIT的长期技术人员Richard Greenblatt取得了联系。他也从未见过这种转变。我检查了一下,得出的结论是开关没用,拿出剪线钳剪断了电线。然后我们打开计算机,它开始安静地工作。
我们仍然不知道此开关如何关闭计算机。有一个假设是在接地触点附近发生了一个小的短路,开关位置的平移改变了电容,因此当持续一百万分之一秒的脉冲通过电路时,电路就被中断了。但是我们不确定。我们只能说开关是魔术。
它仍然在我的地下室。这可能很愚蠢,但我通常将其保持在“更多魔力”位置。
1994年,提出了对此故事的另一种解释。请注意,开关的主体是金属的。假设没有第二根导线的触点连接到主体(通常主体接地,但是有例外)。开关主体已连接至可能已接地的计算机机箱。然后,机器内部的接地电路可能会比机架接地电路具有不同的电势,并且改变开关的位置会导致电压下降或电涌,然后机器会重新启动。这种影响可能是由知道电位差并决定开这种玩笑的人发现的。
OpenOffice在星期二不打印
今天在博客上,我提到了一个有趣的错误。有些人在打印文档时遇到麻烦。后来,有人指出他的妻子抱怨周二无法打印!
在错误报告中,一些人最初抱怨它一定是OpenOffice错误,因为它在所有其他应用程序中打印都没有问题。其他人指出问题来了又去。一位用户找到了解决方案:卸载OpenOffice并擦除系统,然后重新安装(Ubuntu上的任何简单任务)。该用户周二报告说,他的打印问题已解决。
两周后,他(星期二)写道,他的解决方案仍然无效。大约四个月后,Ubuntu黑客的妻子抱怨OpenOffice在星期二没有打印。想象一下这种情况:
妻子:史蒂夫,打印机在星期二关闭。
史蒂夫:今天是打印机休息日,当然它不会在星期二打印。
妻子:我是认真的!我不能在星期二从OpenOffice打印。
史蒂夫:(令人难以置信)好吧,告诉我。
妻子:我不能告诉你。
史蒂夫:(翻白眼)为什么?
妻子:今天是星期三!
史蒂夫:(点头,说话慢点)对。
问题被追溯到名为的程序
file
。 * NIX实用程序使用模板来检测文件类型。例如,如果文件以%!
然后开始PS-Adobe-
,然后是PostScript。看起来OpenOffice正在将数据写入此类文件。周二他穿制服%%CreationDate: (Tue MMM D hh:mm:...)
。Erlang JAM文件的模板中的错误意味着Tue
PostScript文件被识别为Erlang JAM文件,因此,大概没有将其发送给打印。
Erlang JAM文件的模板如下所示:
4 string Tue Jan 22 14:32:44 MET 1991 Erlang JAM file - version 4.2
它看起来应该像这样:
4 string Tue\ Jan\ 22\ 14:32:44\ MET\ 1991 Erlang JAM file - version 4.2
考虑到该程序尝试识别的文件类型众多(超过1600个),模板错误不足为奇。但是比较的顺序也导致频繁的误报。在这种情况下,Erlang JAM类型已映射到PostScript类型。
死亡包
我开始打电话给他们,因为它们正好是死亡包。
Star2Star与一家硬件制造商合作,该制造商已经创建了本地客户端系统的最后两个版本。
大约一年前,我们发布了此硬件的更新。遵循摩尔一贯的法律,一切开始都非常简单。更大,更好,更快,更便宜。新硬件为64位,具有8倍的内存,更多的驱动器,并具有四个Intel千兆以太网端口(我最喜欢的以太网控制器制造商)。关于如何使用这些端口,我们有(并且仍然有)很多想法。一般来说,铁片很美味。
通过性能和功能测试,新颖性大增。速度高且可靠性高。理想地。然后,我们将设备缓慢部署到几个测试站点。当然,问题开始出现。
Google进行的快速搜索表明,英特尔82574L以太网控制器至少存在一些问题。特别是EEPROM的问题,ASPM中的错误,MSI-X的技巧等。我们已经解决了每个问题几个月。而且我们认为我们已经完成了。
但不是。只会变得更糟。
我以为我设计并部署了完美的软件映像(和BIOS)。但是,现实是不同的。模块继续失败。有时它们在重新启动后恢复了,有时却没有。但是,还原模块后,需要对其进行测试。
哇。情况变得怪异。
奇怪的事情继续存在,最后我决定卷起袖子。我很幸运地找到了一个非常耐心和乐于助人的经销商,在我收集数据时,他在手机上与我呆了三个小时。在该客户端点,由于某种原因,以太网控制器可能会在通过网络传输语音流量时掉线。
我将对此进行更详细的介绍。当我说以太网控制器“可能已经坏了”时,这意味着它可能会失败。系统和以太网接口看起来不错,并且在发送了随机流量之后,该接口可能会报告硬件错误(与PHY的通信丢失)并失去连接。开关和接口上的LED实际上熄灭了。控制器死了。
只有关闭电源然后再打开,才有可能使它恢复生命。尝试重新引导内核模块或计算机会导致PCI扫描错误。在物理上拔下机器并再次插入之前,该接口一直保持无效状态。在大多数情况下,对于我们的客户而言,这意味着卸下设备。
在与这个非常耐心的经销商进行调试时,我开始在接口崩溃时停止接收数据包。最后,我确定了一个模式:接口的最后一个数据包始终为
100 Trying provisional response
,并且始终具有一定的长度。不仅如此,我最终将此响应(来自Asterisk)追溯到特定于制造商的一部手机的原始INVITE请求。
我打电话给转销商,召集人,并提供了证据。尽管是星期五晚上,每个人都参与了工作,并使用我们的新设备和该制造商的电话组装了一个测试台。
我们坐在会议室里,开始以最快的速度拨号。原来,我们可以重现该问题!不是在每个电话上,也不是在每个设备上,但我们有时会设法打开以太网控制器,有时我们却没有。断电后,我们再次尝试,成功了。无论如何,任何试图诊断技术问题的人都知道,第一步就是重现问题。我们终于成功了。
相信我,花了很长时间。我知道OSI堆栈的工作方式。我知道软件是如何细分的。我知道SIP数据包的内容不会影响以太网适配器。都是废话
最后,我们设法在数据包到达设备和交换机的镜像端口之间的时间间隔中隔离了问题。原来,问题出在请求
INVITE
而不是响应上100 Trying
。镜像端口上捕获的数据100 Trying
没有响应。
有必要解决这个问题
INVITE
。问题是否与用户空间守护程序处理此软件包有关?也许是传输问题了100 Trying
?我的一位同事建议关闭SIP应用程序,看看问题是否仍然存在。没有此应用,套餐100 Trying
没有传播。
有必要以某种方式改善问题数据包的传输。我们隔离了从电话发送的数据包,
INVITE
并使用播放了tcpreplay
。有效。这是几个月以来的第一次,我们可以通过一个数据包丢弃命令端口。这是一个重大的进步,是时候回家了,也就是在家庭实验室中重复测试台!
在继续我的故事之前,我想告诉您一个我发现的出色的开源应用程序。 Ostinato将您变成数据包主控器。实际上,它的可能性是无限的。没有这个应用程序,我将无法进一步发展。
有了这个多功能的包装工具,我开始尝试。我对发现的结果感到惊讶。
一切始于一个奇怪的SIP / SDP怪癖。看一下此SDP:
v=0
o=- 20047 20047 IN IP4 10.41.22.248
s=SDP data
c=IN IP4 10.41.22.248
t=0 0
m=audio 11786 RTP/AVP 18 0 18 9 9 101
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:0 PCMU/8000
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:9 G722/8000
a=rtpmap:9 G722/8000
a=fmtp:101 0-15
a=rtpmap:101 telephone-event/8000
a=ptime:20
a=sendrecv
是的,这是对的。声音传输建议已重复。这是一个问题,但同样,以太网控制器与此有何关系?好吧,除了没有其他任何事情会增加以太网帧的大小这一事实之外……但是,等等,正在传输的数据包中有很多成功的以太网帧。其中一些更小一些。他们没有问题。我不得不进一步挖掘。在与Ostinato进行了几项功夫诡计并进行了一系列的电气重新连接后,我能够识别出有问题的关系(带有问题框架)。注意:我们将查看十六进制值。
接口崩溃是由特定偏移量处的特定字节值启动的。在我们的例子中,它是十六进制值
32
c 0x47f
。在ASCII中,十六进制32
为2
... 猜猜它来自哪里2
。
a=ptime:20
我们所有的SDP都相同(包括
ptime
)。所有源和目标URI都是相同的。唯一的区别是呼叫者的电话号码,标签和唯一的会话ID。问题数据包具有呼叫ID,标签和分支的这种组合,从而ptime
产生2
带有offset的值0x47f
。
繁荣!使用正确的ID,标签和分支(或任何随机的垃圾),只要行在
ptime
某个地址结束,“好的包”就可以变成“杀手”包。这很奇怪。
生成数据包时,我尝试了不同的十六进制值。事实证明情况更加复杂。事实证明,控制器的行为完全取决于位于第一个接收到的数据包中指定地址的特定值。图片是这样的:
0x47f = 31 HEX (1 ASCII) -
0x47f = 32 HEX (2 ASCII) -
0x47f = 33 HEX (3 ASCII) -
0x47f = 34 HEX (4 ASCII) - (inoculation)
当我说“不影响”时,我的意思是不仅不会杀死接口,而且不会接种(或多或少)。当我说“接口崩溃”时,还记得我的描述吗?接口快死了。完全可以
经过新的测试,我发现在FreeBSD上找到的每个Linux版本都存在问题,甚至在没有可启动媒体的情况下打开机器!这是关于硬件,而不是操作系统。哇。
此外,在Ostinato的帮助下,我能够创建杀手包的不同版本:HTTP POST,ICMP回显请求等。几乎我想要的一切。使用经过修改的HTTP服务器以字节值生成数据(基于标头,主机等),创建第200个HTTP请求以包含死亡数据包并杀死防火墙后的客户端计算机很容易!
我已经解释了整个情况有多奇怪。但是最奇怪的是疫苗。事实证明,如果第一个收到的数据包包含任何值(来自我尝试的值)
1
,2
或者或除外3
,则该接口将不受任何死亡数据包(包含值2
或3
)的影响。此外,代码和属性ptime
一直是10的倍数:10
,20
,30
,40
。根据呼叫ID,标签,分支,IP,URI等的组合(使用该错误的SDP),这些有效属性ptime
将按正确的顺序排列。难以置信!
突然明白了为什么问题偶尔发生。我能够弄清楚真是太神奇了。我从事网络工作已经15年了,从未见过类似的东西。我怀疑我会再见到你。希望...
我联系了英特尔的两名工程师,并给了他们一个演示,以便他们重现问题。经过数周的实验后,他们发现问题出在82574L控制器中的EEPROM。他们给我寄了一个新的EEPROM和一个写工具。不幸的是,我们无法分发它,此外,还需要卸载和重新加载e1000e内核模块,因此该工具不适合我们的环境。幸运的是(对EEPROM电路有一点了解),我能够编写一个bash脚本,然后神奇地
ethtool
保存``固定''值并在出现错误的系统中注册它们。现在我们可以确定问题设备了。在将补丁发送给我们之前,我们已经联系我们的供应商以将补丁应用于所有设备。尚不知道已经售出了多少个这些英特尔以太网控制器。
再增加一个托盘
在2005年,我遇到了一个无法解释的问题。在计划外关闭的第二天(由于飓风),我开始收到来自用户的电话,这些用户抱怨连接数据库时超时。由于我们有一个非常简单的网络(可容纳32个节点,带宽几乎未使用),因此,我警告数据库服务器正常ping 15-20分钟,然后大约两分钟内出现“请求超时”响应。该服务器正在运行性能监视和其他工具,并在各个位置执行ping操作。除服务器外,其余机器可以一直与其他网络成员通信。我搜索了失败的交换机或连接,但找不到随机和间歇性故障的解释。
当我追踪并重新连接各种设备时,我请一位同事观察仓库中交换机上的LED。一位同事在收音机上告诉我,这花了45至50分钟,“这关了,那人起床了。”我问他是否注意到任何规律。
-是的...我注意到了。但是您会认为我很疯狂。每次叉车将货盘从运输大厅运出时,服务器上的两秒钟都会发生超时。
- 什么???
-是的当加载程序开始发送新订单时,服务器将还原。
我跑去看了看叉车,确定他通过打开一些巨大的磁控管标志着订单的成功完成。毫无疑问,来自电容器的电磁波会导致时空连续性中断,并暂时中断位于50米外另一个房间中的服务器网卡的运行。没有。叉车只需在托盘上堆放较大的箱子,在顶部放置较小的箱子,即可使用无线条形码扫描仪扫描每个箱子。啊哈!可能是扫描程序正在访问数据库服务器,从而导致其他查询失败。不。我检查发现扫描仪与它无关。发货大厅中的无线路由器及其UPS已正确配置并正常运行。原因是别的,因为在飓风关闭之前,一切正常。
下一个超时时间一开始,我就跑到货运大厅,看着装载机装满下一个托盘。他将四个大盒的洗发水放在一个空托盘上后,服务器又掉了下来!我不相信发生的事情是荒谬的,又过了五分钟,我取出洗发水放在盒子里,结果还是一样。当我发现运送大厅中的路由器悬挂在货盘上的箱子下方约30厘米处时,我跪下祈祷上帝的怜悯。有一个线索!
当将大箱子放在托盘上时,无线路由器看不到外部仓库的视线。十分钟后,我解决了问题。这是发生了什么。在飓风期间,断电导致唯一未连接UPS的设备掉落-我办公室中的测试无线路由器。默认设置以某种方式将其转变为装运大厅中唯一悬挂的其他无线路由器的中继器。两个设备之间只有没有托盘时才可以相互通信,但是即使那样信号也不会太强。路由器通话时,它们在我的小型网络中创建了一个环路,然后所有其他到数据库服务器的数据包都丢失了。服务器从主路由器拥有自己的交换机,因此作为一个网络节点,它就更远了。其他大多数计算机都在同一16端口交换机上,因此我可以在它们之间ping通而不会出现任何问题。
一秒钟后,我解决了一个困扰了四个小时的问题:关闭了测试路由器的电源。服务器上没有超时。
就像Tron电影一样,仅在Apple IIgs计算机上
我小时候最喜欢的电影之一是《特隆》,该片于1980年代初拍摄。它讲述了一个程序员,这个程序员被“数字化了”,并且被个性化程序所占据的计算机世界所吸引。主角加入了一个抵抗组织,企图推翻压迫者总控制程序(MCP),该程序不断演变,产生了对权力的渴望,并试图接管五角大楼的计算机系统。
在程序中最令人印象深刻的场景之一中,角色在轻便的自行车上竞赛-两轮汽车看起来像摩托车,将墙壁抛在了身后。其中一位主角迫使敌方佩佩拉特人冲入竞技场的墙壁,打了一个通孔。英雄们与他们的对手打交道,逃到了自由之洞-这是推翻MCP的第一步。
当我看电影时,我不知道几年后我会无意间在Apple IIgs计算机上重塑Tron,叛逆程序以及其他所有东西的世界。
这是怎么回事。当我开始学习编程时,我决定用Tron创建一个轻骑自行车游戏。我和我的朋友Marco一起在ORCA / Pascal和65816汇编程序上编写了有关Apple IIgs的程序,在游戏过程中,屏幕涂成黑色并带有白色边框。每行代表一位玩家。我们在屏幕底部连续显示游戏分数。在图形上,它不是最高级的程序,但它既简单又有趣。她看起来像这样:
如果他们坐在一个键盘前,最多可支持四名玩家。这很不方便,但确实有效。我们很少设法让合适的人数使用全部四个照明周期,因此Marco添加了可以合理竞争的计算机控制玩家。
军备竞赛
游戏本来就很有趣,但我们想尝试一下。我们添加了火箭,使玩家有机会逃脱即将发生的事故。正如Marco稍后所述:
人类和人工智能各自拥有三枚可在游戏中使用的导弹。当火箭击中墙壁时,发生了“爆炸”,其背景被涂成黑色,从而去除了先前光周期留下的痕迹。
很快,玩家和计算机就可以用火箭弹摆脱困境。尽管Tron的纯粹主义者会为此而咯咯笑,但影片中的节目却没有火箭的奢华。
逃亡
与所有异常和离奇的事件一样,这也是意外的。
有一次,当我和Marco与两个计算机播放器对战时,我们将一个AI循环困在了自己的墙和屏幕底部之间。像往常一样,他预见到即将发生的事故,发射了火箭。但是这次,他没有挡住墙壁,而是朝屏幕的边界开了枪,看起来像是一个光周期的踪迹。导弹击中了边界,留下了一个光周期大小的洞,计算机立即通过它退出了运动场。当我们穿过得分线时,我们对光周期感到困惑。他轻松地避免了与符号的冲突,然后完全离开了屏幕。
之后,系统立即崩溃了。
当我们试图掌握所发生的事情时,我们的思想在摇摆。计算机找到了摆脱游戏的方法。当光周期离开屏幕时,就像电影中一样,它逃到了计算机内存中。当我们意识到发生了什么事时,我们的下巴掉了下来。
当我们发现程序中的缺陷会定期使整个系统崩溃时,我们该怎么做?我们又做了一遍。首先,我们试图自己超越界限。然后他们强迫计算机再次运行。每次我们都因迷人的系统崩溃而倍受奖励。有时,驱动器指示灯不停闪烁,因为驱动器不断发出声音。其他时候,屏幕上充满无意义的字符,或者扬声器发出尖叫声或低声嗡嗡声。有时这一切都立即发生,并且计算机处于完全混乱的状态。
为什么会这样?为了理解这一点,让我们看一下Apple IIgs计算机的体系结构。
(Un)受保护的内存
Apple IIgs操作系统没有受保护的内存,这种内存出现在以后的操作系统中,这是因为将内存区域分配给程序并受到了外部访问的保护。因此,Apple IIgs下的程序可以读取和写入任何内容(ROM除外)。IIgs使用内存绑定I / O来访问软盘驱动器等设备,因此可以通过从特定的内存区域读取来激活软盘驱动器。这种体系结构允许图形程序直接读取和写入屏幕内存。
该游戏使用了Apple IIgs图形模式之一-超级高分辨率:320x200像素的惊人分辨率以及16种颜色的调色板。为了选择一个调色板,程序员为12位颜色值指定了16个条目(以十六进制格式从0到15或从$ 0到F编号)。为了在屏幕上绘图,您可以直接将颜色读取和写入视频内存。
碰撞检测算法
我们利用了此功能,并通过直接从视频内存读取来实现了崩溃检测器。游戏会根据当前方向为每个光周期计算其下一个位置,并从视频内存中读取该像素。如果位置为空,即由黑色像素表示($ 0调色板中的条目),则游戏继续。但是,如果采取了该位置,则玩家会进入光周期或屏幕的白色框架(进入调色板15或$ F)。例:
屏幕的左上角显示在此处。颜色$ F表示白色边框,颜色$ 1表示玩家的绿灯周期。它如箭头所示向左移动,即下一个像素为空,其颜色为$ 0。如果玩家继续朝这个方向移动超过一圈,他将与墙碰撞(颜色$ F)并断裂。
超越
使用汇编器数学算法确定下一个像素的算法可以快速计算出当前像素上方,下方,左侧或右侧一个像素的内存地址。由于屏幕上的任何像素都是内存中的地址,因此该算法只需计算一个新的地址即可读取。当光周期离开屏幕时,该算法确定了系统内存中的位置以检查是否与墙壁发生碰撞。这意味着光周期现在正在遍历系统内存,无意义地打开位并“崩溃”到内存中。
写入系统内存中的随机位置不是明智的体系结构决策。毫不奇怪,游戏因此而崩溃。人类玩家不会盲目行驶,通常会立即坠毁,这限制了系统问题的范围。人工智能没有这种弱点。计算机立即扫描其周围的位置,以确定是否撞到墙壁并改变方向。也就是说,根据计算机,系统内存与屏幕内存没有什么不同。正如Marco所描述的:
, , . , , 0. «» , . «», - - , , — . , - , .
结果,我们不仅从电影中重新创建了光周期竞赛,而且还重新设计了逃生本身。就像在电影中一样,逃跑产生了巨大的后果。
由于操作系统已获取受保护的内存,因此今天很难重复这种情况。但是我仍然想知道是否有像Tron这样的程序试图逃脱其“受保护的空间”,以试图阻止反叛的AI代码接管五角大楼。
我想找出答案,我们需要等待意识数字化的发明。
坐下来登录
每个程序员都知道调试很困难。尽管对于优秀的调试人员而言,这项工作看起来非常简单。烦躁不安的程序员描述了一个他们花了数小时才能捕获的错误,主人问了几个问题,几分钟后,程序员看到了面前的错误代码。调试专家不会忘记,总是存在逻辑上的解释,无论乍一看系统的行为多么神秘。
IBM约克敦高地研究中心的一个故事说明了这种态度。程序员最近安装了一个新的工作站。当他坐在电脑前时,一切都很好,但是他站立时无法登录。这种行为总是被重现:程序员总是在坐着和站着的时候登录-他甚至不能一次。
我们中的许多人只是坐在那里想知道。电脑如何知道他们是站在电脑前还是坐在电脑前?但是,好的调试器知道一定有原因。首先想到的是电力。地毯下面的电线断了,还是有静电?但是,很少有100%的时间重现电气问题。一位同事最后问了一个正确的问题:程序员在坐着和站着时如何登录?自己尝试。
原因是键盘:两个按钮被颠倒了。当程序员坐下时,他会盲目打字,而这个问题却未被注意到。当他站起来时,这让他感到困惑,他寻找按钮并按下按钮。有了这个提示和一把螺丝刀,调试专家换了个按钮,一切都解决了。
部署在芝加哥的银行系统运行了好几个月。但是当它最初用于处理国际数据时,它意外退出。程序员花了好几天时间在代码周围打转,但找不到一个导致程序终止的命令。当他们仔细观察她的行为时,他们发现如果将厄瓜多尔数据输入该程序,该程序将终止。分析表明,当用户键入大写字母(Quito)的名称时,程序会将其解释为退出命令!
一天,鲍勃·马丁遇到了一个“工作两次”的系统。它正确地处理了第一笔交易,并且在所有后续交易中都存在小问题。重新引导系统后,它再次正确处理了第一个事务,而所有后续事务均失败。当Bob将此行为描述为“运行两次”时,开发人员立即意识到,他们需要寻找一个变量,该变量在加载程序时已正确初始化,但在第一次事务处理后未重置。在所有情况下,正确的问题使明智的程序员能够快速发现令人不快的错误:“当您站着坐着时,您做了什么不同的工作?请告诉我这两种情况下的登录方式,“,”在程序结束之前您输入了什么? “程序在崩溃开始之前是否正常工作?多少次?”
里克·莱姆斯(Rick Lemons)说,他从调试中学到的最好的课程是当他观看魔术师的表演时。他做了很多不可能的把戏,莱蒙斯觉得他相信了。然后,他提醒自己,不可能是不可能的,他尝试了所有技巧来证明这种明显的矛盾。柠檬始于一个不可动摇的真理-物理定律,从中他开始为每种技巧寻找简单的解释。这种态度使Lemons成为我遇到的最好的调试器之一。
我认为最好的调试书是《医疗侦探》由Berton Roueche撰写,并于1991年由Penguin出版。该书的英雄调试了复杂的系统,从中病的人到病重的城市。那里使用的问题解决方法可以直接用于调试计算机系统。这些真实的故事像任何小说一样引人入胜。
500英里电子邮件案例
在这种情况下,这听起来简直不可思议……我几乎拒绝谈论它,因为它是举办会议的绝佳自行车。我对故事进行了一些微调,以保护罪魁祸首,丢弃无关紧要的细节,并总体上使故事更具吸引力。
几年前,我在校园里维护一个电子邮件系统。统计部门的负责人给我打电话。
-我们在发送信件时遇到问题。
- 有什么问题?
“我们不能发送超过500英里的信件。
我cho了咖啡。
- 不明白。
“我们不能向部门发送超过500英里的信件。实际上,还有一点。约520英里。但这是极限。
“嗯……实际上,电子邮件无法正常工作。”我回答,试图控制声音中的恐慌。您不能在与部门主管(甚至是统计部门主管)的对话中表现出恐慌。 -为什么您决定不能发送超过500英里的信件?
“我还没有决定,”他重重地回答。 -当我们注意到几天前发生的事情时,您会看到...-
您等了几天?我用颤抖的声音把他切断了。 -而且你一直都不能发信吗?
-我们可以发送。再也没有……
”“五百英里,是的,”我为他完成了任务。 -清楚但是为什么不早点打电话呢?
“到目前为止,我们没有足够的数据来确定正在发生的事情。
恰恰是这是统计主管。
-无论如何,我让一位地统计学家与之合作...-
地统计学家...-
是的,她绘制了一张地图,显示了我们可以发送信件的半径,略超过500英里。在该区域中有几个地方,我们的信件根本没有或没有定期到达,但在半径范围之外,我们根本无法发送任何东西。
“我明白了。”我说,然后低下了头。 -什么时候开始的?您是在几天前说过的,但我们尚未更改您系统上的任何内容。
-一位顾问来了,打了补丁并重新启动了我们的服务器。但是我打电话给他,他说他没有碰邮件系统。
“回答,让我看看并给您回电,”我回答,几乎不认为自己参与了这样的事情。今天不是四月初。我试图记住是否有人欠我一个恶作剧。
我登录了他们部门的服务器,并发送了一些验证电子邮件。这是在北卡罗莱纳州研究三角区发生的,这封信毫无问题地到达了我的邮箱。发送给里士满,亚特兰大和华盛顿的信件也是如此。也有一封信寄给普林斯顿(400英里)。
但是后来我给孟菲斯(600英里)发了一封信。没来在波士顿,它没有来。在底特律,它没有来。我拿出地址簿,开始通过它发送信件。它到达了纽约(420英里),但没有到达普罗维登斯(580英里)。
我开始怀疑自己的理智。写给北卡罗来纳州的一个朋友,他的提供者在西雅图。幸运的是,这封信没有到达。如果问题与收件人而不是他们的邮件服务器的位置有关,我可能会大哭。
在确定问题确实存在(难以置信)并且可重现之后,我开始分析sendmail.cf文件。他看起来很好。照常。我将其与主目录中的sendmail.cf进行了比较。没有区别-这是我写的文件。而且我很确定我没有包括这个选项
FAIL_MAIL_OVER_500_MILES
。在混乱中,我通过telnet SMTP端口。服务器愉快地回应了来自SunOS的Sendmail标语。
等待... SunOS的Sendmail标语?当时,尽管Sendmail 8已经被完全掺杂,Sun仍在使用其操作系统发送Sendmail 5。由于我是一名出色的系统管理员,因此我将Sendmail 8作为标准配置引入。另外,由于我是一个优秀的sysadmin,所以我写了sendmail.cf,它使用了Sendmail 8中很长的自记录选项和变量名,而不是Sendmail 5中使用的隐蔽标点代码。
一切都准备就绪。然后又again了我已经冷却的咖啡。看起来当顾问“修补服务器”时,他升级了SunOS版本,从中推出了旧版本的Sendmail。幸运的是,sendmail.cf文件幸免了下来,但是现在不匹配了。
事实证明,Sendmail 5(至少是Sun发行的具有许多改进的版本)可以与Sendmail.cf一起用于Sendmail 8,因为大多数规则都是相同的。但是现在无法识别和丢弃新的长配置选项。由于大多数情况下,Sendmail二进制文件中都没有默认值,因此程序未在sendmail.cf中找到任何合适的值并将其重置为零。
这些零值之一是到远程SMTP服务器的连接超时。经过一些试验,结果发现在这台特定的机器上,在正常负载下,零超时将导致断开连接超过三毫秒。
当时,园区网络完全基于交换机。传出数据包没有延迟,直到它通过POP到达另一端的路由器为止。即,到相邻网络中负载较弱的远程主机的连接持续时间很大程度上取决于以光速覆盖的距离,而不取决于路由器的随机延迟。
有点头晕,我在命令行中输入:
$ units
1311 units, 63 prefixes
You have: 3 millilightseconds
You want: miles
* 558.84719
/ 0.0017893979
“ 500英里或更多。”
未完待续。