Responsible re-use of the BluetoothClient object

Topics: Bluetooth - Microsoft, Bluetooth - Widcomm/Broadcom
Jul 7, 2012 at 12:15 AM
Edited Jul 7, 2012 at 12:40 AM

So I have this small app that uses InTheHand to repeatedly connect to a set of bluetooth modules one at a time, do some stuff then disconnect. The modules gets powered down between each cycle and I'd like to be able to repeat this operation thousands of times (it's for a tester) but I keep running into a problem where the app will hang while trying to connect after a while (I've seen it hang after 100 cycles, but it has gone as far as 2000+).

When it hangs, I notice some strange side effects in windows; It no longer recognizes the Bluetooth Adapter being unplugged or plugged back in, device manager freezes as soon as I open it and windows freezes when I try to restart. So signs point to some mis-use of the API.

Here's a rough run-down of what I'm doing:

public class BT_Unit
{
	public BluetoothAddress addr;
	public BluetoothClient cli;
}

public class Tester
{
	private Guid Service;
	private BluetoothRadio btRadio;
	private BluetoothPublicFactory btFactory;
	private IBluetoothSecurity btISecurity;

	private List<BT_Unit> bt_units;

	private void looper(List<BT_Unit> units, byte[] tx_buff, int tx_len)
	{
		while (1) //Freezes after 100-2000+ cycles, causes issues in Windows too
		{
			foreach(BT_Unit unit in units) //Up to four in my tests
			{
				//Connect
				unit.cli = btFactory.CreateBluetoothClient();
				btISecurity.RemoveDevice(unit.addr);
				btISecurity.PairRequest(unit.addr, "");
				Cursor.Current = Cursors.WaitCursor;

				unit.cli.Connect(new BluetoothEndPoint(unit.addr, Service, 2));
				
				//Do stuff
				NetworkStream peerStream = bt_client.GetStream();
				peerStream.Write(tx_buff, 0, tx_len);
				peerStream.Flush();

				//Disconnect
				bt_client.Close();
			}
		}
	}

	public int main()
	{
		Service = BluetoothService.SerialPort;
		btRadio = BluetoothRadio.PrimaryRadio;
		btFactory = btRadio.StackFactory;
		btISecurity = btFactory.BluetoothSecurity;
		
		looper(a_few_test_units, some_buffer, its_length);
		
		return 0;
	}
}

Go easy on me, this is my first time using C# so it's a learning process as well as trying to remember OOP principals. The example above is obviously rediculously simplified, but I included all my core interaction with anything BT realted.

Everything tells me this has a horrific memory leak when I assign unit.cli without calling some variant of free(), but doesn't GC take care of the deferenced BluetoothClients? Are there other parts of the BT standard procedure that I'm neglecting that causes this thing to blow up eventually?

Thanks for reading, great library btw, the documentation has been more than helpful up to this point!

Developer
Jul 8, 2012 at 5:14 PM

I can't see anything wrong with your code. (I'm assuming that the call to bt_client.Close; somehow closes the instance returned by btFactory.CreateBluetoothClient();  If the client is scoped to that block you could replace the bt_client.Close() to a using block).

And anyway it sounds very much as if the dongle is dying.  The whole USB comms of the dongle would appear to be dead.  We've noticed in the past that some dongles are more robust and/or more capable (e.g. number of connections) than others.  Try with a new dongle and see if that helps.

Jul 9, 2012 at 4:20 PM

Thanks for the reply, and Good catch on the bt_client, I forgot to change those after I copy/pasted that portion, the getStream() and close() methods are called on unit.cli, the client object I got from the factory in the connect portion. I changed my connect to an asynchronous connect so I can die a little more gracefully, and I'll try out a different radio and see where that gets me. 

Jul 11, 2012 at 11:31 PM

I took your advice and changed dongles, same make and model (you gotta walk before you run...) and so far things are looking good. I let it run last night and racked up over 5200 connections without a hitch. I wish I understood the problem a little better though. I feel really helpless when such a minor thing causes such a big issue (for my purposes anyway.)

Thanks again for your help Alan

Developer
Jul 12, 2012 at 10:32 PM

Wow. I'm surprised that made a difference. One does hear though that manufacturers sometimes keep the same model number even though they've changed the internal. Perhap that's the case here; or maybe there was just a small hardware fault in the original one...  Glad its helped anyway.