FreeBSD pkg 突然停止引导

FreeBSD pkg suddenly stopped bootstrapping

我已经设置了一个打包程序模板来生成 FreeBSD 10.3 的 vagrant 基础镜像,它至少在 10 月 3 日星期一运行良好 00:34:41 2016 +0300。

昨天我打算继续这个项目的工作,结果发现这不再有效了。所以这里有详细信息。

Packer 执行它必须执行的操作,然后使用 bsdinstall(8) 和以下脚本运行我的脚本来安装 FreeBSD:

PARTITIONS="ada0 { 29G freebsd-ufs /, 5G freebsd-swap, 10G freebsd-ufs /var }"
DISTRIBUTIONS="base.txz kernel.txz"
#!/bin/sh
echo 'WITHOUT_X11="YES"' >> /etc/make.conf
echo 'OPTIONS_UNSET=X11' >> /etc/make.conf
echo 'nameserver 8.8.8.8' >> /etc/resolv.conf
cat >> /etc/rc.conf <<EOF
ifconfig_em0="DHCP"
sshd_enable="YES"
dumpdev="NO"
EOF

env ASSUME_ALWAYS_YES=1 pkg bootstrap #       <<stops here
pkg update    
pkg install -y sudo

[.....snip.....]

reboot

这在引导 pkg 时停止并显示以下消息:

Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:10:amd64/quarterly, please wait...
Signature for pkg not available.
pkg: Error fetching http://pkg.FreeBSD.org/FreeBSD:10:amd64/quarterly/Latest/pkg.txz.sig: Connection reset by peer
A pre-built version of pkg could not be found for your system.
Consider changing PACKAGESITE or installing it from ports: 'ports-mgmt/pkg'.

如果我停止 bsdinstall 脚本并且 chroot /mnt /bin/sh 我可以从上面 URL 获取 pkg.txz.sig 没有任何问题。

任何想法可能是 "connection reset by peer" 的原因? pkg.FreeBSD.org 最近有什么变化吗?

我找不到有关此问题的任何信息。


UPD1

查看 captured traffic -- 该站点确实回答了 200OK,然后断开了 pkg.txz.sig 文件的连接。

但是这个 200OK 数据包包含签名文件和 they are identical 手动 fetch(成功)和 pkg bootstrap(失败)

两个会话相同,因此这可能不是网络问题。


UPD2

truss 也是 not helpful

因此,作为解决方法,我刚刚修改了我的 bsdinstall 脚本以手动获取文件:

[.....snip.....]

#env ASSUME_ALWAYS_YES=1 pkg bootstrap
fetch http://pkg.FreeBSD.org/FreeBSD:10:amd64/quarterly/Latest/pkg.txz
fetch http://pkg.FreeBSD.org/FreeBSD:10:amd64/quarterly/Latest/pkg.txz.sig
pkg add pkg.txz
pkg update

[.....snip.....]

PS:我现在唯一怀疑的是virtualbox版本更新...无论如何降级不是一种选择。 (ISO 校验和被硬编码到模板中,模板和脚本在 git 存储库中,因此不可能发生意外更改)


UPD3

调试环境搭建好了,暂时只隔离了报错的函数

这是来自 http 连接的第二次缓冲区填充(而第一个已经读取了 727 个字节 - 应该是 EOF)...

Here 是带有回溯和断点的小型 gdb 日志。 添加了在系统上进行的 tcpdump 捕获(兼容 wireshark)。

正如我发现的那样,部分问题出在 pkg 上——他们尝试从连接中读取 10240 字节,如果文件较小则期望 EOF,但不知何故在我的系统上当整个远程文件未设置 EOF已经读出来了。

# /release/10.3.0/usr.sbin/pkg/pkg.c

185 char buf[10240];

242 while ((r = fread(buf, 1, sizeof(buf), remote)) > 0) { 

和以下循环两次——第一次读取文件,第二次出现连接重置错误而不是 EOF

# /release/10.3.0/lib/libc/stdio/fread.c

94          resid = count * size;                        # == 10240 here

100         while (resid > (r = fp->_r)) { 
101                 (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
102                 fp->_p += r;
103                 /* fp->_r = 0 ... done in __srefill */
104                 p += r;
105                 resid -= r;
106                 if (__srefill(fp)) {
107                         /* no more input: return partial result */
108                         return ((total - resid) / size);
109                 }
110         }

虽然手动 fetch 成功,因为 size 针对小块进行了调整,他们只要求读取 727 个字节:

# /release/10.3.0/usr.bin/fetch/fetch.c

720                 if (us.size != -1 && us.size - count < B_size &&
721                     us.size - count >= 0)
722                         size = us.size - count;
723                 else
724                         size = B_size;

733                 if ((readcnt = fread(buf, 1, size, f)) < size) { 

...但为什么没有设置 EOF 仍然是一个问题。

已将此发布到 freebsd-pkg 邮件列表。


UPD1

将 Virtualbox 从 5.028 降级到 5.026 并设置了 EOF,_sread()libc/stdio/refill.c:135 returns 0 上并在第 138 行设置了 EOF。

所以 Virtualbox 网络也发生了一些变化。将 Virtualbox 5.026 的 pcap 文件添加到 gist. 5.028 really was the culprit of connection reset - here is captures comparison.

Virtualbox 5.1.8 也有这个bug。版本 5.1.6 工作正常。

在他们的 bugtracker 中打开 ticket #16141