libtorrent
libtorrent copied to clipboard
OpenBSD test fails
2025-06-12T20:47:15.1726875Z TestTrackerList:
2025-06-12T20:47:15.1727068Z TestTrackerList::test_basic : error
2025-06-12T20:47:15.1727226Z
2025-06-12T20:47:15.1727320Z Caught Segmentation fault, dumping stack:
It's been happening for a while. No idea why. I think it's related to threading changes.
Add a sleep to the test, then attach lldb to get the backtrace.
I can't seem to use the sleep() trick to attach to the running process, the issue seems to occur even before the first line in test_basic(), maybe in the test setup itself.
Got a backtrace from the core file (LD_LIBRARY_PATH=./src/.libs:$LD_LIBRARY_PATH lldb test/.libs/LibTorrent_Test_Torrent --core ./LibTorrent_Test_Torrent.core), which also makes it seem like it happens in the setup:
(lldb) target create "test/.libs/LibTorrent_Test_Torrent" --core "./LibTorrent_Test_Torrent.core"
Core file '/root/libtorrent/LibTorrent_Test_Torrent.core' (x86_64) was loaded.
warning: This version of LLDB has no plugin for the language "assembler". Inspection of frame variables will be limited.
(lldb) bt
* thread #1, stop reason = signal SIGABRT
* frame #0: 0x00000a3f567bad7b libc.so.100.3`_thread_sys_thrkill at -:2
frame #1: 0x00000a3f567eb3cb libc.so.100.3`_libc_abort at abort.c:51:8
frame #2: 0x00000a3cd64898f1 LibTorrent_Test_Torrent`(anonymous namespace)::do_test_panic(signum=<unavailable>) at main.cc:53:3
frame #3: 0x00000a3f854bf009
frame #4: 0x00000a3cd649ca2b LibTorrent_Test_Torrent`TestFixtureWithMainNetTrackerThread::tearDown(this=<unavailable>) at test_main_thread.cc:140:30
frame #5: 0x00000a3ed71d2314 libcppunit.so.4.0`CppUnit::TestCaseMethodFunctor::operator()() const + 52
frame #6: 0x00000a3cd649bea3 LibTorrent_Test_Torrent`ExceptionProtector::protect(this=<unavailable>, functor=<unavailable>, context=<unavailable>) at protectors.cc:11:12
frame #7: 0x00000a3ed71cdc06 libcppunit.so.4.0`CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) + 374
frame #8: 0x00000a3ed71da6d9 libcppunit.so.4.0`CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&) + 73
frame #9: 0x00000a3ed71d2026 libcppunit.so.4.0`CppUnit::TestCase::run(CppUnit::TestResult*) + 310
frame #10: 0x00000a3ed71d27a5 libcppunit.so.4.0`CppUnit::TestComposite::doRunChildTests(CppUnit::TestResult*) + 101
frame #11: 0x00000a3ed71d2634 libcppunit.so.4.0`CppUnit::TestComposite::run(CppUnit::TestResult*) + 36
frame #12: 0x00000a3ed71d27a5 libcppunit.so.4.0`CppUnit::TestComposite::doRunChildTests(CppUnit::TestResult*) + 101
frame #13: 0x00000a3ed71d2634 libcppunit.so.4.0`CppUnit::TestComposite::run(CppUnit::TestResult*) + 36
frame #14: 0x00000a3ed71da3f7 libcppunit.so.4.0`CppUnit::TestResult::runTest(CppUnit::Test*) + 39
frame #15: 0x00000a3ed71dd925 libcppunit.so.4.0`CppUnit::TestRunner::run(CppUnit::TestResult&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&) + 69
frame #16: 0x00000a3cd6488e60 LibTorrent_Test_Torrent`main(argc=<unavailable>, argv=<unavailable>) at main.cc:88:12
frame #17: 0x00000a3cd648885b LibTorrent_Test_Torrent`__start + 299
Looking at ktrace/kdump (filtering kbind spam) I think the issue is maybe caused by socketpair -1 errno 24 Too many open files, but then there's some issue down the line (in the protector?) that turns it into a sigsegv? Or maybe that's just how this ends up being reported.
73523 LibTorrent_Test_Torrent CALL kqueue()
73523 LibTorrent_Test_Torrent RET kqueue 126/0x7e
73523 LibTorrent_Test_Torrent CALL mmap(0,0x8000,0x3<PROT_READ|PROT_WRITE>,0x1002<MAP_PRIVATE|MAP_ANON>,-1,0)
73523 LibTorrent_Test_Torrent RET mmap 16891274436608/0xf5cce69a000
73523 LibTorrent_Test_Torrent CALL socketpair(AF_UNIX,0x1<SOCK_STREAM>,0,0x7c7f32ae93c0)
73523 LibTorrent_Test_Torrent RET socketpair -1 errno 24 Too many open files
73523 LibTorrent_Test_Torrent CALL close(126)
73523 LibTorrent_Test_Torrent RET close 0
73523 LibTorrent_Test_Torrent CALL write(1,0xf5ca7492000,0x8)
73523 LibTorrent_Test_Torrent GIO fd 1 wrote 8 bytes
" : error"
73523 LibTorrent_Test_Torrent RET write 8
73523 LibTorrent_Test_Torrent PSIG SIGSEGV caught handler=0xf5a81410650 mask=0<> code=SEGV_MAPERR addr=0x1c trapno=6
73523 LibTorrent_Test_Torrent CALL kbind(0x7c7f32ae87d8,24,0x8fe96fe3b3896fc0)
73523 LibTorrent_Test_Torrent RET kbind 0
73523 LibTorrent_Test_Torrent CALL sigaction(SIGSEGV,0x7c7f32ae8870,0x7c7f32ae8860)
73523 LibTorrent_Test_Torrent STRU struct sigaction { handler=SIG_DFL, mask=0<>, flags=0x2<SA_RESTART> }
73523 LibTorrent_Test_Torrent STRU struct sigaction { handler=0xf5a81410650, mask=0<>, flags=0x2<SA_RESTART> }
73523 LibTorrent_Test_Torrent RET sigaction 0
73523 LibTorrent_Test_Torrent CALL write(1,0xf5ca7492000,0x1)
73523 LibTorrent_Test_Torrent GIO fd 1 wrote 1 bytes
"
"
To confirm this, I tried setting the file descriptors ulimit higher with ulimit -n 1000 (default is 128) and re-running, and this does allow the test to run (and pass!) without issue. I'm not an expert here but I think that this may just be how the ulimit violation is being reported, and if there is some real memory access issue it's in the test crash handling code and not in the real libtorrent code.
Here is the unit test GitHub workflow finally fully passing on OpenBSD, on my branch: https://github.com/ikmckenz/libtorrent/actions/runs/18212219556
After 7.8 comes out and vmactions is updated for it, I'll make a PR for the working config file.
Wonderful