回复:linux-0.1.6-test7
首次公开证据
打开首次公开证据查看 1 个交叉存档
来源说明
Published on GitHub in February 2024 as part of Martti Malmi's testimony in the COPA v. Wright trial
终于碰上一个容易解决的问题了。我看出它会如何在初始下载之类的长时间操作中发生。TryLock 的错误与数据库部分无关。修复会包含在 test8 中。
现在,我已经在 32 位 Linux 上用连续不断的海量请求冲击程序,3 次复现了 db::open/close 异常。看来,即便只是定期关闭 wallet.dat 数据库来刷新它,也会触发 db::close 异常。我正在 Linux 上禁用钱包刷新功能。在 Linux 上,准备退出之前我们绝不会关闭数据库句柄。到目前为止,禁用这项功能后没有再出现异常。
我还在实现有序的初始区块下载。它不再简单地一次请求所有区块,而是每次分批请求 500 个。这样,它会在重试超时之前收到这些区块,因此除非确实没有收到,或者对方速度太慢,否则它不应该再向其他节点请求。改动位于被请求方一侧,所以只有当你的初始区块下载来自运行新版本的节点时,这项功能才会显现出来。
在发送 test8 前,我还要多测试一些。
我用 test7 和一个全新的数据目录启动。区块下载速度快多了。以前使用 Linux 构建版要花几分钟,这次只用了大约 15 秒。下载区块时它崩溃过一次,终端里显示了以下消息。
../include/wx/thrimpl.cpp(50): assert "m_internal" failed in TryLock(): wxMutex::TryLock(): not initialized [in child thread] Trace/breakpoint trap
我附上了日志文件,但重新启动比特币之前忘了备份,所以我不确定崩溃发生在日志文件中的哪个位置。
幸运的是,我还没有遇到段错误。以前各个构建版本发生段错误的频率差别很大,所以我会继续运行,如果遇到任何问题就告诉你。
测试版 7:
运行前请备份你的数据目录,以防万一。
这是针对 Db::open/Db::close“Bad file descriptor”异常的变通办法。它也可能让初始区块下载更快。这个办法是打开数据库句柄,并在程序整个运行期间保持打开,这其实本来就是更常见的做法。如果我们不再反复关闭和打开,错误应该就没有机会发生。
唯一的例外是 wallet.dat,写入完成后我仍会关闭它,以便把交易日志刷新到 dat 文件中,使这个 dat 文件能够独立使用。这样,如果有人在比特币运行时进行备份,得到的 wallet.dat 无须数据库交易日志也能单独有效。
这是对数据库处理方式的一次重构,因此我们可能会遇到一些新的死锁。通常如果发生死锁,要么 UI 会停止重绘,要么即使仍显示 Generating,也会停止使用 CPU。
英文原文
展开英文原文
Finally an easy one. I see a way that could happen on a long operation such as the initial download. The TryLock bug is unrelated to the db stuff. Fix will be in test8.
I've been able to reproduce the db::open/close exception 3 times now on 32-bit linux by hitting it with a continuous flood of non-stop requests. It looks like even periodically closing the wallet.dat database to flush it gets the db::close exceptions. I'm disabling the wallet flush feature on Linux. On Linux we'll never close a database handle until we're ready to exit. So far with this disabled, no exceptions.
I'm also implementing the orderly initial block download. Instead of naively requesting all the blocks at once, it'll request batches of 500 at a time. This way, it'll receive the blocks before the retry timeout, so it shouldn't go requesting it from other nodes unless it actually doesn't receive them or it's too slow. The change is in the requestee's side, so this functionality won't be visible until your initial block download is coming from a node that has the new version.
I'm going to test this some more before sending test8.
I started with a fresh data directory with test7. Blocks started to download much faster. It only took about 15 seconds where it took a few minutes previously with the Linux build. It crashed once while it was downloading blocks with the following message in the terminal.
../include/wx/thrimpl.cpp(50): assert "m_internal" failed in TryLock(): wxMutex::TryLock(): not initialized [in child thread] Trace/breakpoint trap
I've included my log file, but I forgot to back it up before restarting bitcoin, so I'm not sure at what point in the log file the crash occurred.
Fortunately I haven't encountered the segmentation fault yet. The frequency of segmentation faults in the previous builds varied quite a bit, so I'll keep running it and let you know if i run into any problems.
test 7:
Backup your data directory before running this, just in case.
Workaround for the Db::open/Db::close "Bad file descriptor" exception. Might also make the initial block download faster. The workaround is to open the database handles and keep them open for the duration of the program, which is actually the more common thing to do anyway. If we're not closing and opening all the time, the error shouldn't get a chance to happen.
The one exception is wallet.dat, which I still close after writing is finished so I can flush the transaction logs into the dat file, making the dat file standalone. That way if someone does a backup while Bitcoin is running, they'll get a wallet.dat that is valid by itself without the database transaction logs.
This is a restructuring of the database handling, so we might find some new deadlocks. Usually if it deadlocks, either the UI will stop repainting, or it'll stop using CPU even though it still says Generating.