pkg(7) is not bootstrapping, possible error in working with libfetch

Evgeny Petrov freeglider at gmail.com
Wed Nov 2 02:54:17 UTC 2016


Installing using packer and virtualbox 5.028 r111378 of
FreeBSD-10.3-RELEASE-amd64-disc1.iso using bsdinstall with
​
the following script:
---

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
---

This stops at bootstrapping pkg with the message:

---
Signature for pkg not available.
pkg: Error fetching
http://pkg.FreeBSD.org/FreeBSD:10:amd64/quarterly/Latest/pkg.txz.sig:
Connection reset by peer
---

If I break the script and chroot /mnt - I can get the file using fetch(1)
without problem.
Adding two fetches(for txz and sig files) and "pkg add pkg.txz" to my
script solved the problem.

As I've found out using gdb - the problem is that pkg passes size==10240 to
fread() function (pkg.c:242), which leads
​ ​
to two iterations of (fread.c:100) while{} loop.

First iteration reads whole file (pkg.txz.sig 727bytes).

Second iteration sets error flag due to connection reset, and returns -1.
This triggers the message(ferror() inpkg.c:254) while the temporary file
/tmp/pkg.txz.sig.[random symbols] is already there and filled with the
remotefile content.

The reason fetch(1) is working - they use their buffer size only if it's
less than remote file size.
Otherwise they set it to the size of remote file (== 727bytes in my case)
​ ​
(fetch/fetch.c:720-724).
So the __srefill (fread.c:106) is called only once not trying to read from
closed connection.

If I lower the bandwidth to 10kbit/s using "ipfw pipe" pkg(7) fails at the
pkg.txz stage, "Connection reset by peer".
If I run multiple times without bw limiting - approximately 1/20 of tries
succedes.

It seems to be race condition - if connection is closed after the attempt
of second buffer refill - it sets EOF and continiues to run, if connection
is closed eariler - it returns error and unlink temporary file and exits.

Tcpdump capture can be found here:
https://gist.github.com/petruchito/82877b1954e7dc8f4502a696683c9385

There's more detailed description in the following StackOverflow question:
http://stackoverflow.com/questions/40209220/freebsd-pkg-suddenly-stopped-bootstrapping



--
Sincerely yours,
Evgeny Petrov


More information about the freebsd-pkg mailing list