Bug 144727 - Crash when unloading plugin
Summary: Crash when unloading plugin
Status: RESOLVED FIXED
Alias: None
Product: ktorrent
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: unspecified Linux
: NOR crash
Target Milestone: ---
Assignee: Joris Guisson
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-04-26 22:42 UTC by Thomas Tanghus
Modified: 2007-05-27 13:30 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Tanghus 2007-04-26 22:42:58 UTC
Version:           2.1.4 (using KDE 3.5.5, Kubuntu (dapper) 4:3.5.5-0ubuntu1~dapper2)
Compiler:          Target: i486-linux-gnu
OS:                Linux (i686) release 2.6.15-28-686

KTorrent crashed when I unloaded the scheduler plugin. Wasn't able to reproduce it.
Backtrace below:

[KCrash handler]
#6  0xb5ab4ea0 in kt::InfoWidget::update ()
   from /usr/lib/kde3/ktinfowidgetplugin.so
#7  0xb5aabc6c in kt::InfoWidgetPlugin::guiUpdate ()
   from /usr/lib/kde3/ktinfowidgetplugin.so
#8  0xb7de3982 in kt::PluginManager::updateGuiPlugins ()
   from /usr/lib/libktorrent-2.1.4.so
#9  0x080690de in QGList::count ()
#10 0x08069665 in QGList::count ()
#11 0xb6ece051 in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#12 0xb6eceaec in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#13 0xb7263686 in QTimer::timeout () from /usr/lib/libqt-mt.so.3
#14 0xb6ef3049 in QTimer::event () from /usr/lib/libqt-mt.so.3
#15 0xb6e63f3e in QApplication::internalNotify () from /usr/lib/libqt-mt.so.3
#16 0xb6e6413a in QApplication::notify () from /usr/lib/libqt-mt.so.3
#17 0xb75fc1cd in KApplication::notify () from /usr/lib/libkdecore.so.4
#18 0xb6df5157 in QApplication::sendEvent () from /usr/lib/libqt-mt.so.3
#19 0xb6e5592b in QEventLoop::activateTimers () from /usr/lib/libqt-mt.so.3
#20 0xb6e08f67 in QEventLoop::processEvents () from /usr/lib/libqt-mt.so.3
#21 0xb6e7ca2f in QEventLoop::enterLoop () from /usr/lib/libqt-mt.so.3
#22 0xb6e62a79 in QApplication::enter_loop () from /usr/lib/libqt-mt.so.3
#23 0xb7ad0ecf in KIO::NetAccess::enter_loop () from /usr/lib/libkio.so.4
#24 0xb7b144b5 in KIO::NetAccess::synchronousRunInternal ()
   from /usr/lib/libkio.so.4
#25 0xb7b145e2 in KIO::NetAccess::synchronousRun () from /usr/lib/libkio.so.4
#26 0xb7e0f641 in bt::WaitJob::execute () from /usr/lib/libktorrent-2.1.4.so
#27 0xb5b214c4 in kt::UPnPPrefWidget::~UPnPPrefWidget ()
   from /usr/lib/kde3/ktupnpplugin.so
#28 0xb5b20321 in kt::UPnPPrefPage::deleteWidget ()
   from /usr/lib/kde3/ktupnpplugin.so
#29 0x0807110e in QValueList<QCString>::detachInternal ()
#30 0xb5b1f6c4 in kt::UPnPPlugin::unload () from /usr/lib/kde3/ktupnpplugin.so
#31 0xb7de3c4c in kt::PluginManager::unloadAll ()
   from /usr/lib/libktorrent-2.1.4.so
#32 0xb7de890b in kt::PluginManagerPrefPage::onUnloadAll ()
   from /usr/lib/libktorrent-2.1.4.so
#33 0xb7df3c5c in kt::PluginManagerPrefPage::qt_invoke ()
   from /usr/lib/libktorrent-2.1.4.so
#34 0xb6ece051 in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#35 0xb6eceaec in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#36 0xb726a007 in QButton::clicked () from /usr/lib/libqt-mt.so.3
#37 0xb6f696f6 in QButton::mouseReleaseEvent () from /usr/lib/libqt-mt.so.3
#38 0xb6f08825 in QWidget::event () from /usr/lib/libqt-mt.so.3
#39 0xb6e63f3e in QApplication::internalNotify () from /usr/lib/libqt-mt.so.3
#40 0xb6e644c8 in QApplication::notify () from /usr/lib/libqt-mt.so.3
#41 0xb75fc1cd in KApplication::notify () from /usr/lib/libkdecore.so.4
#42 0xb6df51c5 in QApplication::sendSpontaneousEvent ()
   from /usr/lib/libqt-mt.so.3
#43 0xb6df0873 in QETWidget::translateMouseEvent ()
   from /usr/lib/libqt-mt.so.3
#44 0xb6deed59 in QApplication::x11ProcessEvent () from /usr/lib/libqt-mt.so.3
#45 0xb6e084db in QEventLoop::processEvents () from /usr/lib/libqt-mt.so.3
#46 0xb6e7ca2f in QEventLoop::enterLoop () from /usr/lib/libqt-mt.so.3
#47 0xb6e62a79 in QApplication::enter_loop () from /usr/lib/libqt-mt.so.3
#48 0xb70815c4 in QDialog::exec () from /usr/lib/libqt-mt.so.3
#49 0x080695e9 in QGList::count ()
#50 0xb6ece051 in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#51 0xb6eceaec in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#52 0xb7801607 in KAction::activated () from /usr/lib/libkdeui.so.4
#53 0xb78346a2 in KAction::slotActivated () from /usr/lib/libkdeui.so.4
#54 0xb78e33d4 in KAction::slotPopupActivated () from /usr/lib/libkdeui.so.4
#55 0xb78e38e5 in KAction::qt_invoke () from /usr/lib/libkdeui.so.4
#56 0xb6ece051 in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#57 0xb7261582 in QSignal::signal () from /usr/lib/libqt-mt.so.3
#58 0xb6eeb7c8 in QSignal::activate () from /usr/lib/libqt-mt.so.3
#59 0xb6ff3149 in QPopupMenu::mouseReleaseEvent () from /usr/lib/libqt-mt.so.3
#60 0xb780ccfd in KPopupMenu::mouseReleaseEvent () from /usr/lib/libkdeui.so.4
#61 0xb6f08825 in QWidget::event () from /usr/lib/libqt-mt.so.3
#62 0xb6e63f3e in QApplication::internalNotify () from /usr/lib/libqt-mt.so.3
#63 0xb6e644c8 in QApplication::notify () from /usr/lib/libqt-mt.so.3
#64 0xb75fc1cd in KApplication::notify () from /usr/lib/libkdecore.so.4
#65 0xb6df51c5 in QApplication::sendSpontaneousEvent ()
   from /usr/lib/libqt-mt.so.3
#66 0xb6df05c0 in QETWidget::translateMouseEvent ()
   from /usr/lib/libqt-mt.so.3
#67 0xb6deed59 in QApplication::x11ProcessEvent () from /usr/lib/libqt-mt.so.3
#68 0xb6e084db in QEventLoop::processEvents () from /usr/lib/libqt-mt.so.3
#69 0xb6e7ca2f in QEventLoop::enterLoop () from /usr/lib/libqt-mt.so.3
#70 0xb6e7c952 in QEventLoop::exec () from /usr/lib/libqt-mt.so.3
#71 0xb6e62a4d in QApplication::exec () from /usr/lib/libqt-mt.so.3
#72 0x08063f70 in ?? ()
#73 0xb66eaea2 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
#74 0x08063a21 in ?? ()
Comment 1 Joris Guisson 2007-04-27 20:22:36 UTC
We will see if we can reproduce this
Comment 2 Joris Guisson 2007-05-27 13:30:22 UTC
SVN commit 668722 by guisson:

Revamped unloading of plugins, there is now a shutdown method 
which can be overriden by plugins who which to do some ExitOperations when they are unloaded.
This fixes bug 144727.

BUG: 144727



 M  +4 -0      libktorrent/interfaces/plugin.cpp  
 M  +12 -0     libktorrent/interfaces/plugin.h  
 M  +36 -0     libktorrent/pluginmanager.cpp  
 M  +5 -0      plugins/upnp/upnpplugin.cpp  
 M  +1 -0      plugins/upnp/upnpplugin.h  
 M  +4 -0      plugins/upnp/upnpprefpage.cpp  
 M  +7 -1      plugins/upnp/upnpprefpage.h  
 M  +15 -23    plugins/upnp/upnpprefwidget.cpp  
 M  +7 -0      plugins/upnp/upnpprefwidget.h  


--- trunk/extragear/network/ktorrent/libktorrent/interfaces/plugin.cpp #668721:668722
@@ -40,5 +40,9 @@
 	void Plugin::guiUpdate()
 	{
 	}
+	
+	void Plugin::shutdown(bt::WaitJob* )
+	{
+	}
 }
 #include "plugin.moc"
--- trunk/extragear/network/ktorrent/libktorrent/interfaces/plugin.h #668721:668722
@@ -23,6 +23,11 @@
 #include <ktversion.h>
 #include <kparts/plugin.h>
 
+namespace bt
+{
+	class WaitJob;
+}
+
 namespace kt
 {
 	class CoreInterface;
@@ -78,6 +83,13 @@
 		 * GUI updates.
 		 */
 		virtual void guiUpdate();
+		
+		/**
+		 * This should be implemented by plugins who need finish of some stuff which might take some time.
+		 * These operations must be finished or killed by a timeout before we can proceed with unloading the plugin. 
+		 * @param job The WaitJob which monitors the plugin
+		 */
+		virtual void shutdown(bt::WaitJob* job);
 
 		const QString & getName() const {return name;}
 		const QString & getAuthor() const {return author;}
--- trunk/extragear/network/ktorrent/libktorrent/pluginmanager.cpp #668721:668722
@@ -23,6 +23,7 @@
 #include <util/log.h>
 #include <util/error.h>
 #include <util/fileops.h>
+#include <util/waitjob.h>
 #include <torrent/globals.h>
 #include <interfaces/guiinterface.h>
 #include "pluginmanager.h"
@@ -114,6 +115,20 @@
 		Plugin* p = plugins.find(name);
 		if (!p)
 			return;
+		
+		// first shut it down properly
+		bt::WaitJob* wjob = new WaitJob(2000);
+		try
+		{
+			p->shutdown(wjob);
+			if (wjob->needToWait())
+				bt::WaitJob::execute(wjob);
+		}
+		catch (Error & err)
+		{
+			Out(SYS_GEN|LOG_NOTICE) << "Error when unloading plugin: " << err.toString() << endl;
+		}
+		delete wjob;
 
 		gui->removePluginGui(p);
 		p->unload();
@@ -146,6 +161,27 @@
 
 	void PluginManager::unloadAll(bool save)
 	{
+		// first properly shutdown all plugins
+		bt::WaitJob* wjob = new WaitJob(2000);
+		try
+		{
+			bt::PtrMap<QString,Plugin>::iterator i = plugins.begin();
+			while (i != plugins.end())
+			{
+				Plugin* p = i->second;
+				p->shutdown(wjob);
+				i++;
+			}
+			if (wjob->needToWait())
+				bt::WaitJob::execute(wjob);
+		}
+		catch (Error & err)
+		{
+			Out(SYS_GEN|LOG_NOTICE) << "Error when unloading all plugins: " << err.toString() << endl;
+		}
+		delete wjob;
+		
+		// then unload them
 		bt::PtrMap<QString,Plugin>::iterator i = plugins.begin();
 		while (i != plugins.end())
 		{
--- trunk/extragear/network/ktorrent/plugins/upnp/upnpplugin.cpp #668721:668722
@@ -82,6 +82,11 @@
 		sock = 0;
 	}
 	
+	void UPnPPlugin::shutdown(bt::WaitJob* job)
+	{
+		pref->shutdown(job);
+	}
+	
 	bool UPnPPlugin::versionCheck(const QString & version) const
 	{
 		return version == KT_VERSION_MACRO;
--- trunk/extragear/network/ktorrent/plugins/upnp/upnpplugin.h #668721:668722
@@ -39,6 +39,7 @@
 
 		virtual void load();
 		virtual void unload();
+		virtual void shutdown(bt::WaitJob* job);
 		virtual bool versionCheck(const QString& version) const;
 	private:
 		UPnPMCastSocket* sock;
--- trunk/extragear/network/ktorrent/plugins/upnp/upnpprefpage.cpp #668721:668722
@@ -59,4 +59,8 @@
 	void UPnPPrefPage::updateData()
 	{
 	}
+	
+	void UPnPPrefPage::shutdown(bt::WaitJob* job)
+	{
+	}
 }
--- trunk/extragear/network/ktorrent/plugins/upnp/upnpprefpage.h #668721:668722
@@ -22,6 +22,11 @@
 
 #include <interfaces/prefpageinterface.h>
 
+namespace bt
+{
+	class WaitJob;
+}
+
 namespace kt
 {
 	class UPnPMCastSocket;
@@ -44,7 +49,8 @@
 		virtual void createWidget(QWidget* parent);
 		virtual void deleteWidget();
 		virtual void updateData();
-
+		
+		void shutdown(bt::WaitJob* job);
 	};
 
 }
--- trunk/extragear/network/ktorrent/plugins/upnp/upnpprefwidget.cpp #668721:668722
@@ -50,30 +50,22 @@
 	UPnPPrefWidget::~UPnPPrefWidget()
 	{
 		bt::Globals::instance().getPortList().setListener(0);
-		if (def_router)
+	}
+	
+	void UPnPPrefWidget::shutdown(bt::WaitJob* job)
+	{
+		if (!def_router)
+			return;
+		
+		net::PortList & pl = bt::Globals::instance().getPortList();
+		if (pl.count() == 0)
+			return;
+		
+		for (net::PortList::iterator i = pl.begin(); i != pl.end();i++)
 		{
-			try
-			{
-				net::PortList & pl = bt::Globals::instance().getPortList();
-				
-				if (pl.count() == 0)
-					return;
-			
-				bt::WaitJob* job = new WaitJob(1000);
-				for (net::PortList::iterator i = pl.begin(); i != pl.end();i++)
-				{
-					net::Port & p = *i;
-					if (p.forward)
-						def_router->undoForward(p,job);
-				}
-				
-				// wait for operations to finish or timeout
-				bt::WaitJob::execute(job);
-			}
-			catch (Error & e)
-			{
-				Out(SYS_PNP|LOG_DEBUG) << "Error : " << e.toString() << endl;
-			}
+			net::Port & p = *i;
+			if (p.forward)
+				def_router->undoForward(p,job);
 		}
 	}
 	
--- trunk/extragear/network/ktorrent/plugins/upnp/upnpprefwidget.h #668721:668722
@@ -27,6 +27,11 @@
 
 class KListViewItem;
 
+namespace bt
+{
+	class WaitJob;
+}
+
 namespace kt
 {
 	
@@ -41,6 +46,8 @@
 		UPnPPrefWidget(QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
 		virtual ~UPnPPrefWidget();
 		
+		void shutdown(bt::WaitJob* job);
+		
 	
 	public slots:
 		/**