• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 491
  • Last Modified:

How to detect the root cause for an exception?

This is a question for a general debugging approach related to exceptions. Although I am an experienced programmer, I ran out of ideas how to track down my problem. I hope someone can help with hints and tool recommendations.

The project:
- Client/server architecture using windows sockets
- Windows XP
- Visual Studio .NET 2003
- MFC
- Server opens/closes MIDI ports to receive MIDI messages
- Using the open source lib "DirectMidi"

The problem:
- Exception in server when closing the MIDI input port under certain conditions (see below for details)

Problem details:
- The usual workflow is:
START: Start server, start client, connect client to server, send "START" command to server, server opens MIDI input port and handles incoming MIDI messages.
STOP: Send "STOP" command to server, disconnect client, terminate client, terminate server

Above workflows work flawlessly.

Here is the problem workflow:
STOP: After server receiver "START" command, terminate the client (disconnect). Then terminate the server ==> exception.

Exception details:
Now we can look into the actual code.

m_pPort is an instance of DirectMusicPort8.

When calling "hr = m_pPort->SetReadNotificationHandle(NULL);" to terminate notifications, an access violation occurs. The debugger shows that m_pPort seems to be valid (no NULL pointer).

As you can see I have already protected the variable m_pPort with a critical section. Nevertheless it seems to get "somehow" corrupted when I terminate the client before sending the server the "STOP" signal. (NOTE: exception occurs when the server is then terminated).

I don't understand this. It seems that the m_pPort gets corrupted somehow. But I cannot track down when or where. I have protected all access to this variable.

The only cause I can think of is that my socket implementation overwrites parts of the memory of m_pPort when I terminate the client, because the problem only occurs when the client is terminated while the server is receiving MIDI messages (i.e. the MIDI port is opened and therefor the m_pPort object has been created). I have reviewed my socket code, but couldn't find any suspicious parts.

How can I track down when/where the m_pPort gets corrupted?


HRESULT CInputPort::TerminateNotification() {
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
	HRESULT hr = DM_FAILED;
 
	CSingleLock portLock ( &m_portCritSec );
	if ( portLock.Lock() ) {
		if (m_pPort)
		{
//   ==> EXCEPTION HAPPENS BELOW!
			hr = m_pPort->SetReadNotificationHandle(NULL);
			// Ends the read notification
			m_ProcessActive = FALSE;		// Tells the thread to exit	
			SetEvent(m_hEvent);	 
			CloseHandle(m_hEvent);
			m_hEvent = NULL;
			// Waits for the receiver thread termination
			WaitForSingleObject(m_hTerminationEvent,THREAD_TIMEOUT);
			CloseHandle(m_hTerminationEvent);
			m_hTerminationEvent = NULL;
		}
	}
	portLock.Unlock();
 
	return hr;
}

Open in new window

0
hirnsieb
Asked:
hirnsieb
  • 2
1 Solution
 
hirnsiebAuthor Commented:
I have made an interesting observation regarding my problem described above:

Whenever the client disconnects (while the server is waiting of MIDI messages), two DLLs are unloaded in the server:

'myServer.exe': Unloaded 'C:\WINDOWS\system32\dmsynth.dll'
'myServer.exe': Unloaded 'C:\WINDOWS\system32\dmusic.dll'

That mustbe the root cause! Unloading those two DLLs makes my DirectMusicPort object certainly invalid!

The new question now is: Why do those DLLs get unloaded?? I still have the reference to the DirectMusicPort object. Further, when the client is disconnecting there is only pure socket handling, no relation to DirectMusic at all. Nevertheless, the DLLs get unloaded. So I assume that there is some sort of other error here. Any ideas?
0
 
hirnsiebAuthor Commented:
I have solved the problem. As described in my previous post, the DirectMusic DLLs get unloaded when the client closed the socket connection. Then my m_pPort variable (IDirectMusicPort) has broken references.

I still don't understand why the scheduler unloads the DLL while I still have instance of classes that use this DLL.

Anyway, I now have a global CDirectMusic object (from the DirectMidi Lib that I am using). I never use this object, but as long it is in scope, the DLLs dont get unloaded. Problem solved.
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now