Summary: | KTorrent crash after several minutes seeding many torrents | ||
---|---|---|---|
Product: | [Applications] ktorrent | Reporter: | Alexey Shildyakov <ashl1future> |
Component: | general | Assignee: | Joris Guisson <joris.guisson> |
Status: | RESOLVED FIXED | ||
Severity: | crash | ||
Priority: | NOR | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Compiled Sources | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: | valgrind log |
Description
Alexey Shildyakov
2010-12-19 15:49:13 UTC
Sorry. I submit attachments for another bug 259814 Attachment 55073 [details] Attachment 55074 [details] Attachment 55075 [details] I have seen that one a few times myself, thought I fixed it with a commit on the same day (cf258c805c536876b278b2e8e18c4d94440f23e8). Are you sure were running that version ? Hmm... Cannot find that commit. The latest commited today I can see: libktorrent: 01740395b688a01b777125be31607a426bbb1db4 ktorrent: 043144139b0560052fec0c6934143609c7c22c6b, 0dab80755cb920cd356cbf1651d10cc8dc6670e0 Yes. I'm sure to running that version. Now I recompiled (from that incident I compile ktorrent and libktorrent simultaneously) to commits: libktorrent: 01740395b688a01b777125be31607a426bbb1db4 ktorrent: 043144139b0560052fec0c6934143609c7c22c6b And the problem still exists. Application: KTorrent (ktorrent), signal: Segmentation fault pthread_cond_timedwait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:212 in ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S [Current thread is 1 (Thread 0x7f007000c760 (LWP 28681))] Thread 10 (Thread 0x7f0057fff710 (LWP 28683)): [KCrash Handler] #6 0x00000000055cae40 in ?? () #7 0x00007f006d7343eb in QCoreApplicationPrivate::checkReceiverThread (this=<value optimized out>, receiver=0x5b59130) at kernel/qcoreapplication.cpp:349 #8 0x00007f006c7e6e86 in QApplication::notify (this=0x7fffe51e4980, receiver=0x7f0057ffe4e0, e=0x7f0057ffeb90) at kernel/qapplication.cpp:3737 #9 0x000000000043de6c in kt::App::notify (this=0x7fffe51e4980, receiver=0x5b59130, event=0x7f0057ffeb90) at /var/tmp/portage/net-p2p/ktorrent-9999/work/ktorrent-9999/ktorrent/app.cpp:97 #10 0x00007f006d73158b in QCoreApplication::notifyInternal (this=0x7fffe51e4980, receiver=0x5b59130, event=0x7f0057ffeb90) at kernel/qcoreapplication.cpp:732 #11 0x00007f006d7643fa in sendEvent (this=0x2398c60) at kernel/qcoreapplication.h:215 #12 QTimerInfoList::activateTimers (this=0x2398c60) at kernel/qeventdispatcher_unix.cpp:603 #13 0x00007f006d761178 in timerSourceDispatch (source=<value optimized out>) at kernel/qeventdispatcher_glib.cpp:184 #14 idleTimerSourceDispatch (source=<value optimized out>) at kernel/qeventdispatcher_glib.cpp:231 #15 0x00007f0067c5c399 in g_main_dispatch (context=0x23989b0) at gmain.c:2149 #16 g_main_context_dispatch (context=0x23989b0) at gmain.c:2702 #17 0x00007f0067c60220 in g_main_context_iterate (context=0x23989b0, block=<value optimized out>, dispatch=<value optimized out>, self=<value optimized out>) at gmain.c:2780 #18 0x00007f0067c603c2 in g_main_context_iteration (context=0x23989b0, may_block=1) at gmain.c:2843 #19 0x00007f006d760e3e in QEventDispatcherGlib::processEvents (this=0x24bd410, flags=<value optimized out>) at kernel/qeventdispatcher_glib.cpp:415 #20 0x00007f006d730192 in QEventLoop::processEvents (this=<value optimized out>, flags=) at kernel/qeventloop.cpp:149 #21 0x00007f006d73055d in QEventLoop::exec (this=0x7f0057ffee20, flags=) at kernel/qeventloop.cpp:201 #22 0x00007f006d62f0f8 in QThread::exec (this=<value optimized out>) at thread/qthread.cpp:490 #23 0x00007f006d631bc7 in QThreadPrivate::start (arg=0x24bd850) at thread/qthread_unix.cpp:285 #24 0x00007f006d39dc3a in start_thread (arg=<value optimized out>) at pthread_create.c:301 #25 0x00007f006bbd2a9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115 Thread 9 (Thread 0x7f00577fe710 (LWP 28684)): #0 0x00007f006bbc9d03 in __poll (fds=<value optimized out>, nfds=<value optimized out>, timeout=500) at ../sysdeps/unix/sysv/linux/poll.c:87 #1 0x00007f006fad2d11 in net::Poll::poll (this=0x7f00577fdd50, timeout=<value optimized out>) at /var/tmp/portage/net-libs/libktorrent-9999/work/libktorrent-9999/src/net/poll.cpp:99 #2 0x00007f006fb4a517 in dht::RPCServer::Private::run (this=<value optimized out>) at /var/tmp/portage/net-libs/libktorrent-9999/work/libktorrent-9999/src/dht/rpcserver.cpp:95 #3 0x00007f006d631bc7 in QThreadPrivate::start (arg=0x7f0058016c40) at thread/qthread_unix.cpp:285 #4 0x00007f006d39dc3a in start_thread (arg=<value optimized out>) at pthread_create.c:301 #5 0x00007f006bbd2a9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115 Thread 8 (Thread 0x7f005cc38710 (LWP 28686)): #0 pthread_cond_timedwait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:212 #1 0x00007f00549bd1e1 in metronom_sync_loop (this=0x50cb5e0) at metronom.c:870 #2 0x00007f006d39dc3a in start_thread (arg=<value optimized out>) at pthread_create.c:301 #3 0x00007f006bbd2a9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115 Thread 7 (Thread 0x7f004c72a710 (LWP 28687)): #0 0x00007f006bbc9d03 in __poll (fds=<value optimized out>, nfds=<value optimized out>, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:87 #1 0x00007f0067c5ff7d in g_main_context_poll (context=0x505beb0, block=<value optimized out>, dispatch=<value optimized out>, self=<value optimized out>) at gmain.c:3093 #2 g_main_context_iterate (context=0x505beb0, block=<value optimized out>, dispatch=<value optimized out>, self=<value optimized out>) at gmain.c:2775 #3 0x00007f0067c603c2 in g_main_context_iteration (context=0x505beb0, may_block=1) at gmain.c:2843 #4 0x00007f006d760e8e in QEventDispatcherGlib::processEvents (this=0x50588a0, flags=<value optimized out>) at kernel/qeventdispatcher_glib.cpp:417 #5 0x00007f006d730192 in QEventLoop::processEvents (this=<value optimized out>, flags=) at kernel/qeventloop.cpp:149 #6 0x00007f006d73055d in QEventLoop::exec (this=0x7f004c729dc0, flags=) at kernel/qeventloop.cpp:201 #7 0x00007f006d62f0f8 in QThread::exec (this=<value optimized out>) at thread/qthread.cpp:490 #8 0x00007f0054c17030 in Phonon::Xine::XineThread::run (this=0x505ee60) at /var/tmp/portage/media-sound/phonon-4.4.3/work/phonon-4.4.3/xine/xinethread.cpp:143 #9 0x00007f006d631bc7 in QThreadPrivate::start (arg=0x505ee60) at thread/qthread_unix.cpp:285 #10 0x00007f006d39dc3a in start_thread (arg=<value optimized out>) at pthread_create.c:301 #11 0x00007f006bbd2a9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115 Thread 6 (Thread 0x7f004bd24710 (LWP 28688)): #0 0x00007f006bbc9d03 in __poll (fds=<value optimized out>, nfds=<value optimized out>, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:87 #1 0x00007f0066114853 in poll_func (ufds=0x50ce810, nfds=<value optimized out>, timeout=<value optimized out>, userdata=0x505e910) at pulse/thread-mainloop.c:75 #2 0x00007f0066104816 in pa_mainloop_poll (m=0x505e810) at pulse/mainloop.c:879 #3 0x00007f0066105bee in pa_mainloop_iterate (m=0x505e810, block=<value optimized out>, retval=0x0) at pulse/mainloop.c:961 #4 0x00007f0066105cd0 in pa_mainloop_run (m=0x505e810, retval=0x0) at pulse/mainloop.c:979 #5 0x00007f0066114633 in thread (userdata=0x505e670) at pulse/thread-mainloop.c:94 #6 0x00007f00650ee217 in internal_thread_func (userdata=0x505ccf0) at pulsecore/thread-posix.c:83 #7 0x00007f006d39dc3a in start_thread (arg=<value optimized out>) at pthread_create.c:301 #8 0x00007f006bbd2a9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115 Thread 5 (Thread 0x7f0047522710 (LWP 28689)): #0 pthread_cond_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00007f00549cb323 in fifo_peek_int (fifo=0x50f17f0, blocking=1) at audio_out.c:348 #2 0x00007f00549ccd3a in fifo_peek (this_gen=<value optimized out>) at audio_out.c:388 #3 ao_loop (this_gen=<value optimized out>) at audio_out.c:1015 #4 0x00007f006d39dc3a in start_thread (arg=<value optimized out>) at pthread_create.c:301 #5 0x00007f006bbd2a9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115 Thread 4 (Thread 0x7f0040bd7710 (LWP 28731)): #0 pthread_cond_timedwait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:212 #1 0x00007f006d63121a in thread_sleep (ti=0x7f0040bd6da0) at thread/qthread_unix.cpp:435 #2 0x00007f006d631370 in QThread::msleep (msecs=<value optimized out>) at thread/qthread_unix.cpp:461 #3 0x00007f006facdecd in net::DownloadThread::update (this=0x2359460) at /var/tmp/portage/net-libs/libktorrent-9999/work/libktorrent-9999/src/net/downloadthread.cpp:91 #4 0x00007f006face7c9 in net::NetworkThread::run (this=0x2359460) at /var/tmp/portage/net-libs/libktorrent-9999/work/libktorrent-9999/src/net/networkthread.cpp:48 #5 0x00007f006d631bc7 in QThreadPrivate::start (arg=0x2359460) at thread/qthread_unix.cpp:285 #6 0x00007f006d39dc3a in start_thread (arg=<value optimized out>) at pthread_create.c:301 #7 0x00007f006bbd2a9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115 Thread 3 (Thread 0x7f003bfff710 (LWP 28732)): #0 pthread_cond_timedwait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:212 #1 0x00007f006d63121a in thread_sleep (ti=0x7f003bffeda0) at thread/qthread_unix.cpp:435 #2 0x00007f006d631370 in QThread::msleep (msecs=<value optimized out>) at thread/qthread_unix.cpp:461 #3 0x00007f006faccdb5 in net::UploadThread::update (this=0x2359ad0) at /var/tmp/portage/net-libs/libktorrent-9999/work/libktorrent-9999/src/net/uploadthread.cpp:89 #4 0x00007f006face7c9 in net::NetworkThread::run (this=0x2359ad0) at /var/tmp/portage/net-libs/libktorrent-9999/work/libktorrent-9999/src/net/networkthread.cpp:48 #5 0x00007f006d631bc7 in QThreadPrivate::start (arg=0x2359ad0) at thread/qthread_unix.cpp:285 #6 0x00007f006d39dc3a in start_thread (arg=<value optimized out>) at pthread_create.c:301 #7 0x00007f006bbd2a9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115 Thread 2 (Thread 0x7f003b7fe710 (LWP 28733)): #0 pthread_cond_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00007f006d6329d3 in wait (this=<value optimized out>, mutex=0x7f003c005410, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:88 #2 QWaitCondition::wait (this=<value optimized out>, mutex=0x7f003c005410, time=18446744073709551615) at thread/qwaitcondition_unix.cpp:160 #3 0x00007f006fad23b2 in net::ReverseResolverThread::run (this=0x7f003c005400) at /var/tmp/portage/net-libs/libktorrent-9999/work/libktorrent-9999/src/net/reverseresolver.cpp:123 #4 0x00007f006d631bc7 in QThreadPrivate::start (arg=0x7f003c005400) at thread/qthread_unix.cpp:285 #5 0x00007f006d39dc3a in start_thread (arg=<value optimized out>) at pthread_create.c:301 #6 0x00007f006bbd2a9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115 Thread 1 (Thread 0x7f007000c760 (LWP 28681)): #0 pthread_cond_timedwait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:212 #1 0x00007f006d63121a in thread_sleep (ti=0x7fffe51e4570) at thread/qthread_unix.cpp:435 #2 0x00007f006d631370 in QThread::msleep (msecs=<value optimized out>) at thread/qthread_unix.cpp:461 #3 0x00007f0054c35e0a in Phonon::Xine::Backend::~Backend (this=0x505b900, __in_chrg=<value optimized out>) at /var/tmp/portage/media-sound/phonon-4.4.3/work/phonon-4.4.3/xine/backend.cpp:111 #4 0x00007f006a434fa7 in Phonon::FactoryPrivate::~FactoryPrivate (this=0x7f0058341390, __in_chrg=<value optimized out>) at /var/tmp/portage/media-sound/phonon-4.4.3/work/phonon-4.4.3/phonon/factory.cpp:221 #5 0x00007f006bb36045 in __run_exit_handlers (status=1, listp=0x7f006be614a8, run_list_atexit=true) at exit.c:78 #6 0x00007f006bb36095 in exit (status=-451001100) at exit.c:100 #7 0x00007f006c861548 in qt_xio_errhandler () at kernel/qapplication_x11.cpp:773 #8 0x00007f006e731d40 in KApplication::xioErrhandler (this=0x7fffe51e4980, dpy=0x23ab630) at /var/tmp/portage/kde-base/kdelibs-4.5.4/work/kdelibs-4.5.4/kdeui/kernel/kapplication.cpp:416 #9 0x00007f0069e84c0e in _XIOError (dpy=0x23ab630) at XlibInt.c:1602 #10 0x00007f0069e83add in _XEventsQueued (dpy=0x23ab630, mode=<value optimized out>) at xcb_io.c:307 #11 0x00007f0069e73cef in XEventsQueued (dpy=0x23ab630, mode=2) at Pending.c:43 #12 0x00007f006c89cd5c in x11EventSourceCheck (s=0x2393fd0) at kernel/qguieventdispatcher_glib.cpp:87 #13 0x00007f0067c5f603 in g_main_context_check (context=0x2389720, max_priority=0, fds=<value optimized out>, n_fds=-1) at gmain.c:2658 #14 0x00007f0067c5ff97 in g_main_context_iterate (context=0x2389720, block=<value optimized out>, dispatch=<value optimized out>, self=<value optimized out>) at gmain.c:2777 #15 0x00007f0067c603c2 in g_main_context_iteration (context=0x2389720, may_block=1) at gmain.c:2843 #16 0x00007f006d760e3e in QEventDispatcherGlib::processEvents (this=0x2385d30, flags=<value optimized out>) at kernel/qeventdispatcher_glib.cpp:415 #17 0x00007f006c89cba6 in QGuiEventDispatcherGlib::processEvents (this=0x7fffe51e44f4, flags=<value optimized out>) at kernel/qguieventdispatcher_glib.cpp:204 #18 0x00007f006d730192 in QEventLoop::processEvents (this=<value optimized out>, flags=) at kernel/qeventloop.cpp:149 #19 0x00007f006d73055d in QEventLoop::exec (this=0x7fffe51e48e0, flags=) at kernel/qeventloop.cpp:201 #20 0x00007f006d732dfb in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1009 #21 0x000000000042d352 in main (argc=<value optimized out>, argv=<value optimized out>) at /var/tmp/portage/net-p2p/ktorrent-9999/work/ktorrent-9999/ktorrent/main.cpp:176 Another backtrace. Now KTorrent crashed after several hours. Is it a problem with mediaplayer plugin? I haven't seen this XIO error crash since the fix I mentioned above. Could be that I'm lucky. My current hypothesis is that it is caused by doing X stuff in the wrong thread. Hm... The problem doesn't exist with disabled utp protocol. Ran into this XIOError again yesterday Could you run ktorrent under valgrind until you see it ? You seem to be able to reproduce this easier then me. valgrind --log-file=vg.log --num-callers=50 /usr/bin/ktorrent --nofork Created attachment 55793 [details]
valgrind log
libktorrent: d0deb0260781c69ec7a7eb23f39e0db133bc0757
ktorrent: 087f5be3f1db04868c00a3a8e691f0d0111aeda2
valgrind was crashed too
commit dddb07872180ae70eb86fcdbdfe4e7270a7b6432 branch master Author: Joris <joris.guisson@gmail.com> Date: Mon Jan 10 19:06:47 2011 +0100 Move timers out of Connection object and into UTPServer. This fixes a crash due to cleaning up timer in the wrong thread. BUG: 260712 diff --git a/ChangeLog b/ChangeLog index f1b82d8..c85fc6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ Changes in 1.1rc1: - Fix bug in UPnP so that it works properly with D-Link DIR 635 routers - Fix crash due to manipulating timers in the wrong thread (261903) - Fix compiler warning in TimeEstimator (262618) +- Fix crash due to cleaning up timer in the wrong thread (260712) Changes in 1.1beta1: - Use UTF-8 as default codec in bt::Value::toString diff --git a/src/download/packet.cpp b/src/download/packet.cpp index adfe4c0..c8ab706 100644 --- a/src/download/packet.cpp +++ b/src/download/packet.cpp @@ -108,7 +108,7 @@ namespace bt if (ReadUint32(data,9) != req.getOffset()) return false; - if (ReadUint32(data,13) != req.getLength()) + if (size - 13 != req.getLength()) return false; return true; diff --git a/src/utp/connection.cpp b/src/utp/connection.cpp index d6ccd5b..e439326 100644 --- a/src/utp/connection.cpp +++ b/src/utp/connection.cpp @@ -44,7 +44,7 @@ namespace utp } Connection::Connection(bt::Uint16 recv_connection_id, Type type, const net::Address& remote, Transmitter* transmitter) - : transmitter(transmitter) + : transmitter(transmitter),timer_id(-1) { stats.type = type; stats.remote = remote; @@ -668,19 +668,14 @@ namespace utp if (QThread::currentThread() != thread()) emit doDelayedStartTimer(); else - timer.start(stats.timeout,this); + delayedStartTimer(); } void Connection::delayedStartTimer() { - timer.start(stats.timeout,this); + if (timer_id != -1) + transmitter->cancelTimer(timer_id); + timer_id = transmitter->scheduleTimer(self.toStrongRef(),stats.timeout); } - - void Connection::timerEvent(QTimerEvent* event) - { - Q_UNUSED(event); - handleTimeout(); - } - } diff --git a/src/utp/connection.h b/src/utp/connection.h index 693df92..d6064cf 100644 --- a/src/utp/connection.h +++ b/src/utp/connection.h @@ -161,6 +161,9 @@ namespace utp /// Set a weak pointer to self void setWeakPointer(WPtr ptr) {self = ptr;} + /// Handle a timeout + void handleTimeout(); + private: void sendSYN(); void sendState(); @@ -173,8 +176,6 @@ namespace utp void checkIfClosed(); void sendDataPacket(const QByteArray & packet); void sendDataPacket(const QByteArray & packet, bt::Uint16 seq_nr, const TimeValue & now); - virtual void timerEvent(QTimerEvent* event); - void handleTimeout(); void startTimer(); void checkState(); @@ -197,8 +198,8 @@ namespace utp bool fin_sent; TimeValue last_packet_sent; DelayWindow* delay_window; - QBasicTimer timer; Connection::WPtr self; + int timer_id; friend class UTPServer; }; @@ -219,6 +220,12 @@ namespace utp /// Called when the connection is closed virtual void closed(Connection::Ptr conn) = 0; + + /// Schedule a timer for a connection + virtual int scheduleTimer(Connection::Ptr conn,bt::Uint32 timeout) = 0; + + /// Kill a previously started timer + virtual void cancelTimer(int timer_id) = 0; }; } diff --git a/src/utp/tests/connectiontest.cpp b/src/utp/tests/connectiontest.cpp index d44644c..661ae62 100644 --- a/src/utp/tests/connectiontest.cpp +++ b/src/utp/tests/connectiontest.cpp @@ -54,6 +54,37 @@ public: Q_UNUSED(conn); } + QMap<int,Connection::WPtr> timers; + + virtual int scheduleTimer(Connection::Ptr conn, Uint32 timeout) + { + int timer_id = startTimer(timeout); + timers.insert(timer_id,conn.toWeakRef()); + return timer_id; + } + + virtual void cancelTimer(int timer_id) + { + killTimer(timer_id); + timers.remove(timer_id); + } + + virtual void timerEvent(QTimerEvent* ev) + { + int tid = ev->timerId(); + killTimer(tid); + QMap<int,Connection::WPtr>::iterator i = timers.find(tid); + if (i != timers.end()) + { + Connection::Ptr ptr = i.value().toStrongRef(); + if (ptr) + ptr->handleTimeout(); + timers.erase(i); + } + + ev->accept(); + } + QByteArray buildPacket(bt::Uint32 type,bt::Uint32 recv_conn_id,bt::Uint32 send_conn_id,bt::Uint16 seq_nr,bt::Uint16 ack_nr) { TimeValue tv; diff --git a/src/utp/utpserver.cpp b/src/utp/utpserver.cpp index e0abb63..5714894 100644 --- a/src/utp/utpserver.cpp +++ b/src/utp/utpserver.cpp @@ -544,5 +544,37 @@ namespace utp i++; } } + + int UTPServer::scheduleTimer(Connection::Ptr conn, Uint32 timeout) + { + int timer_id = startTimer(timeout); + d->active_timers.insert(timer_id, Connection::WPtr(conn)); + return timer_id; + } + + void UTPServer::cancelTimer(int timer_id) + { + killTimer(timer_id); + d->active_timers.remove(timer_id); + } + + + void UTPServer::timerEvent(QTimerEvent* ev) + { + int timer_id = ev->timerId(); + killTimer(timer_id); + + QMap<int,Connection::WPtr>::iterator i = d->active_timers.find(timer_id); + if (i != d->active_timers.end()) + { + Connection::Ptr conn = i.value().toStrongRef(); + if (conn) + conn->handleTimeout(); + + d->active_timers.erase(i); + } + + ev->accept(); + } } \ No newline at end of file diff --git a/src/utp/utpserver.h b/src/utp/utpserver.h index dcf4a33..f90fb07 100644 --- a/src/utp/utpserver.h +++ b/src/utp/utpserver.h @@ -82,6 +82,9 @@ namespace utp virtual void stateChanged(Connection::Ptr conn, bool readable, bool writeable); virtual void closed(Connection::Ptr conn); virtual void customEvent(QEvent* ev); + virtual void timerEvent(QTimerEvent* ev); + virtual int scheduleTimer(Connection::Ptr conn, Uint32 timeout); + virtual void cancelTimer(int timer_id); signals: void handlePendingConnectionsDelayed(); diff --git a/src/utp/utpserver_p.h b/src/utp/utpserver_p.h index 24b863c..ee9ec8d 100644 --- a/src/utp/utpserver_p.h +++ b/src/utp/utpserver_p.h @@ -102,6 +102,7 @@ namespace utp QList<net::ServerSocket::Ptr> sockets; bool running; QMap<quint16,Connection::Ptr> connections; + QMap<int,Connection::WPtr> active_timers; UTPServerThread* utp_thread; QMutex mutex; bt::PtrMap<net::Poll*,PollPipePair> poll_pipes; commit 9a5d70fed69866624b7bba87df50947679b73561 branch 1.1 Author: Joris <joris.guisson@gmail.com> Date: Mon Jan 10 19:06:47 2011 +0100 Backport to 1.1: Move timers out of Connection object and into UTPServer. This fixes a crash due to cleaning up timer in the wrong thread. CCBUG: 260712 diff --git a/ChangeLog b/ChangeLog index 33dde23..cebc1cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ Changes in 1.1rc1: - Fix bug in UPnP so that it works properly with D-Link DIR 635 routers - Fix crash due to manipulating timers in the wrong thread (261903) - Fix compiler warning in TimeEstimator (262618) +- Fix crash due to cleaning up timer in the wrong thread (260712) Changes in 1.1beta1: - Use UTF-8 as default codec in bt::Value::toString diff --git a/src/download/packet.cpp b/src/download/packet.cpp index adfe4c0..c8ab706 100644 --- a/src/download/packet.cpp +++ b/src/download/packet.cpp @@ -108,7 +108,7 @@ namespace bt if (ReadUint32(data,9) != req.getOffset()) return false; - if (ReadUint32(data,13) != req.getLength()) + if (size - 13 != req.getLength()) return false; return true; diff --git a/src/utp/connection.cpp b/src/utp/connection.cpp index d6ccd5b..e439326 100644 --- a/src/utp/connection.cpp +++ b/src/utp/connection.cpp @@ -44,7 +44,7 @@ namespace utp } Connection::Connection(bt::Uint16 recv_connection_id, Type type, const net::Address& remote, Transmitter* transmitter) - : transmitter(transmitter) + : transmitter(transmitter),timer_id(-1) { stats.type = type; stats.remote = remote; @@ -668,19 +668,14 @@ namespace utp if (QThread::currentThread() != thread()) emit doDelayedStartTimer(); else - timer.start(stats.timeout,this); + delayedStartTimer(); } void Connection::delayedStartTimer() { - timer.start(stats.timeout,this); + if (timer_id != -1) + transmitter->cancelTimer(timer_id); + timer_id = transmitter->scheduleTimer(self.toStrongRef(),stats.timeout); } - - void Connection::timerEvent(QTimerEvent* event) - { - Q_UNUSED(event); - handleTimeout(); - } - } diff --git a/src/utp/connection.h b/src/utp/connection.h index 693df92..d6064cf 100644 --- a/src/utp/connection.h +++ b/src/utp/connection.h @@ -161,6 +161,9 @@ namespace utp /// Set a weak pointer to self void setWeakPointer(WPtr ptr) {self = ptr;} + /// Handle a timeout + void handleTimeout(); + private: void sendSYN(); void sendState(); @@ -173,8 +176,6 @@ namespace utp void checkIfClosed(); void sendDataPacket(const QByteArray & packet); void sendDataPacket(const QByteArray & packet, bt::Uint16 seq_nr, const TimeValue & now); - virtual void timerEvent(QTimerEvent* event); - void handleTimeout(); void startTimer(); void checkState(); @@ -197,8 +198,8 @@ namespace utp bool fin_sent; TimeValue last_packet_sent; DelayWindow* delay_window; - QBasicTimer timer; Connection::WPtr self; + int timer_id; friend class UTPServer; }; @@ -219,6 +220,12 @@ namespace utp /// Called when the connection is closed virtual void closed(Connection::Ptr conn) = 0; + + /// Schedule a timer for a connection + virtual int scheduleTimer(Connection::Ptr conn,bt::Uint32 timeout) = 0; + + /// Kill a previously started timer + virtual void cancelTimer(int timer_id) = 0; }; } diff --git a/src/utp/tests/connectiontest.cpp b/src/utp/tests/connectiontest.cpp index d44644c..661ae62 100644 --- a/src/utp/tests/connectiontest.cpp +++ b/src/utp/tests/connectiontest.cpp @@ -54,6 +54,37 @@ public: Q_UNUSED(conn); } + QMap<int,Connection::WPtr> timers; + + virtual int scheduleTimer(Connection::Ptr conn, Uint32 timeout) + { + int timer_id = startTimer(timeout); + timers.insert(timer_id,conn.toWeakRef()); + return timer_id; + } + + virtual void cancelTimer(int timer_id) + { + killTimer(timer_id); + timers.remove(timer_id); + } + + virtual void timerEvent(QTimerEvent* ev) + { + int tid = ev->timerId(); + killTimer(tid); + QMap<int,Connection::WPtr>::iterator i = timers.find(tid); + if (i != timers.end()) + { + Connection::Ptr ptr = i.value().toStrongRef(); + if (ptr) + ptr->handleTimeout(); + timers.erase(i); + } + + ev->accept(); + } + QByteArray buildPacket(bt::Uint32 type,bt::Uint32 recv_conn_id,bt::Uint32 send_conn_id,bt::Uint16 seq_nr,bt::Uint16 ack_nr) { TimeValue tv; diff --git a/src/utp/utpserver.cpp b/src/utp/utpserver.cpp index e0abb63..5714894 100644 --- a/src/utp/utpserver.cpp +++ b/src/utp/utpserver.cpp @@ -544,5 +544,37 @@ namespace utp i++; } } + + int UTPServer::scheduleTimer(Connection::Ptr conn, Uint32 timeout) + { + int timer_id = startTimer(timeout); + d->active_timers.insert(timer_id, Connection::WPtr(conn)); + return timer_id; + } + + void UTPServer::cancelTimer(int timer_id) + { + killTimer(timer_id); + d->active_timers.remove(timer_id); + } + + + void UTPServer::timerEvent(QTimerEvent* ev) + { + int timer_id = ev->timerId(); + killTimer(timer_id); + + QMap<int,Connection::WPtr>::iterator i = d->active_timers.find(timer_id); + if (i != d->active_timers.end()) + { + Connection::Ptr conn = i.value().toStrongRef(); + if (conn) + conn->handleTimeout(); + + d->active_timers.erase(i); + } + + ev->accept(); + } } \ No newline at end of file diff --git a/src/utp/utpserver.h b/src/utp/utpserver.h index dcf4a33..f90fb07 100644 --- a/src/utp/utpserver.h +++ b/src/utp/utpserver.h @@ -82,6 +82,9 @@ namespace utp virtual void stateChanged(Connection::Ptr conn, bool readable, bool writeable); virtual void closed(Connection::Ptr conn); virtual void customEvent(QEvent* ev); + virtual void timerEvent(QTimerEvent* ev); + virtual int scheduleTimer(Connection::Ptr conn, Uint32 timeout); + virtual void cancelTimer(int timer_id); signals: void handlePendingConnectionsDelayed(); diff --git a/src/utp/utpserver_p.h b/src/utp/utpserver_p.h index 24b863c..ee9ec8d 100644 --- a/src/utp/utpserver_p.h +++ b/src/utp/utpserver_p.h @@ -102,6 +102,7 @@ namespace utp QList<net::ServerSocket::Ptr> sockets; bool running; QMap<quint16,Connection::Ptr> connections; + QMap<int,Connection::WPtr> active_timers; UTPServerThread* utp_thread; QMutex mutex; bt::PtrMap<net::Poll*,PollPipePair> poll_pipes; |