What happens to a FS Plugin when i exit TC?

Discuss and announce Total Commander plugins, addons and other useful tools here, both their usage and their development.

Moderators: Hacker, petermad, Stefan2, white

Post Reply
djorge
Senior Member
Senior Member
Posts: 422
Joined: 2003-07-03, 12:48 UTC
Location: Portugal

What happens to a FS Plugin when i exit TC?

Post by *djorge »

Hi,

In my FS plugin i have a thread a thread for logging which is cleaned in the main class destructor.

What is bugging me is that sometimes (when i quit TC) it seems that i'm getting a deadlock, because the logging thread does not show any activity, and TC window frame becomes white as if it wasn't processing any messages, or waiting for something else.

But if i disable the logging thread the symptom is gone.

I am unable to debug this problem.

Any hint?
______________________
David Jorge
Personal License #117854
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

You may terminate this thread or to change some global variable so thread will exit itself - you should do this during call to DllMain with fdwReason=DLL_PROCESS_DETACH.

E.g. in my VirtualPanel plugin I have configuration dialog that runs in separate thread to allow using TC while its open - so I send to that window exit message and wait until it is closed before returning from DllMain. Also I stop all timers in DllMain and wait until its process functions finish work (they run also in separate threads).
djorge
Senior Member
Senior Member
Posts: 422
Joined: 2003-07-03, 12:48 UTC
Location: Portugal

Post by *djorge »

Thanks MVV. I didn't know about DLL_PROCESS_DETACH.

Will try that.
______________________
David Jorge
Personal License #117854
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

Usually there are 4 values for fdwReason: DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH. Since you're using only one module instance you should do nothing on two last.
djorge
Senior Member
Senior Member
Posts: 422
Joined: 2003-07-03, 12:48 UTC
Location: Portugal

Post by *djorge »

The problem is that my dll is a MFC dll and i'm getting some errors saying that DllMain is already defined. Even trying this http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/d86b96a2-a5c9-4bfc-98e1-61b55e50ecae is not compiling...
______________________
David Jorge
Personal License #117854
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

If you're using MFC, perhaps you should insert finalization code into another place - according to MFC principles. Just refer to MSDN MFC documentation.

Now I created MFC DLL project (I called it MFCDLL), it made some files for me, I read the TODO comments and I see that I should put initialization code into CMFCDLLApp::CMFCDLLApp() function (i.e. class constructor). It is logical that I should put finalization code into that class's destructor - just need to add it into a class's interface and write code. So, initialization code you should put into CMFCDLLApp::CMFCDLLApp() function instead of DllMain, and finalization code - into CMFCDLLApp::~CMFCDLLApp() function instead of DllMain.

E.g. I have default predefined class in <project_name>.h file:

Code: Select all

class C<project_name>App : public CWinApp
{
public:
	C<project_name>App();

// Overrides
public:
	virtual BOOL InitInstance();

	DECLARE_MESSAGE_MAP()
};
And constructor's realization in <project_name>.cpp:

Code: Select all

C<project_name>App::C<project_name>App()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance

	MessageBox(0, L"Hello, I'm initialized!", L"C<project_name>App::C<project_name>App()", 0);
}
I need to add destructor into a class:

Code: Select all

class C<project_name>App : public CWinApp
{
public:
	C<project_name>App();
	~C<project_name>App(); // destructor

// Overrides
public:
	virtual BOOL InitInstance();

	DECLARE_MESSAGE_MAP()
};
And its realization e.g. below constructor's realization:

Code: Select all

C<project_name>App::C<project_name>App()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance

	MessageBox(0, L"Hello, I'm initialized!", L"C<project_name>App::C<project_name>App()", 0);
}

C<project_name>App::~C<project_name>App()
{
	MessageBox(0, L"Bye, I'm finalized!", L"C<project_name>App::~C<project_name>App()", 0);
}
Now when I'm loading DLL, hello message appears, and when I'm unloading it, bye message appears!

But if you read comment for constructor, you will see recommendation to place significant initialization in InitInstance. According to MSDN there is a function ExitInstance that is called for finalization, you just need to define it:

Code: Select all

class C<project_name>App : public CWinApp
{
public:
	C<project_name>App();
	~C<project_name>App(); // destructor

// Overrides
public:
	virtual BOOL InitInstance();
	virtual int ExitInstance(); // exit instance function

	DECLARE_MESSAGE_MAP()
};
And its code e.g. just below InitInstance's code:

Code: Select all

BOOL CMFCDLLApp::InitInstance()
{
	CWinApp::InitInstance(); // call to base class function - don't remove it

	MessageBox(0, L"Hey, I'm significantly initialized!", L"BOOL CMFCDLLApp::InitInstance()", 0);

	return TRUE;
}

int CMFCDLLApp::ExitInstance()
{
	MessageBox(0, L"Sorry, I'm finalized!", L"int CMFCDLLApp::ExitInstance()", 0);

	return CWinApp::ExitInstance(); // call to base class function - don't remove it
}
Now when DLL is loading, I see hello message, then hey message - constructor and InitInstance are called, then my DLL is ready to work. When it is terminated, I see sorry message and then bye message - ExitInstance and destructor are called.

So, you may terminate your background threads in ExitInstance function, or in destructor - you have a choice. :)
Don't forget that your main class is destroyed after call to destructor, so if your background threads still active, they may try to access to destroyed objects - effect is unpredictable!
djorge
Senior Member
Senior Member
Posts: 422
Joined: 2003-07-03, 12:48 UTC
Location: Portugal

Post by *djorge »

2MVV
Thanks for the explanation. :)

I added ExitInstance and i am terminating my thread there.
______________________
David Jorge
Personal License #117854
Post Reply