Today I've faced with a crash in KTorrent.
My system is Kubuntu 18.04 based on Qt 5.9.5
KTorrent settings has TCP and uTP enabled with uTP primary.
The app crashes just after I change a port number in Settings/Network/Port and press Apply button.
gdb doesn't show anything useful:
[Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 0x00007f8a6ec330b4 in __GI___libc_read (fd=18, buf=0x5607c2cc9a78, nbytes=16384) at ../sysdeps/unix/sysv/linux/read.c:27 27 ../sysdeps/unix/sysv/linux/read.c: No such file or directory. (gdb) continue Continuing. Thread 5 "utp::UTPServerT" received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x7f8a550ab700 (LWP 28650)] 0x00007f8a6fb1dbe4 in QSocketNotifier::type() const () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 (gdb) quit
stdout seems to have these messages related to the problem:
Warning: QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread Warning: QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
The crash happens after call to the globals.getUTPServer().changePort(port); in void Core::applySettings()
On libktorrent side its happen shortly after d->sockets.clear(); in bool UTPServer::changePort(bt::Uint16 p). Debugger stops at exec(); in void UTPServerThread::run()
According to my understanding this happens because d->sockets content as well as UTPServer instance were moved to another thread in void UTPServer::start() and UTPServerThread constructor. While globals.getUTPServer().changePort(port); is called in KTorrent main thread.
This problem seems to exist for a long time, and always trigger warnings but didn't crash the app. After I moved to 18.04 with Qt 5.9.5 this has started to crash the app.
The TCP Server seems to be executed in the main thread and doesn't have this problem.
There may be plenty of ways to fix this. The easiest one (but may be not the best one) is to avoid calling changePort(port); for UTPServer and stop/start it with the right port instead. In libktorrent's bool Globals::initUTPServer(Uint16 port) the utp_server->changePort() is called before utp_server->start() spawns a new thread. This is proposed here.
I would like to know if this problem is reproducible on other machines and probably someone would like to make UTPServer::changePort() a thread-safe in libktorrent itself instead of walkaronding in its client app.
Feel free to add relevant revewers for this.