Sunday, 10 June 2012

Stone Code Sober (also, don't use ConcurrentBag in Mono)

Ugh. Saturday night, sans alcohol, post-Prometheus. Sobriety on a weekend evening can only mean one thing... staying up till fucking 4am and writing code.

As it happens, I did have something to try and achieve. Namely, getting some prototype Spring.Net-based code working in Mono, running under XSP, running on an Ubuntu box.

The code itself is based on some of the same ideas as a current piece of work - a custom http handler and framework that is built for speed and simplicity. At the heart of it is a message bus with attached listeners waiting for commands and an application context to be delivered. The listeners act on the context and it ends up holding the output state ready for the response to be marshalled. It is quite straightforward and /very/ fast, utilising singleton objects from Spring.Net.

Now, I have an Ubuntu box (shard, a little ultra-small-form-factor Dell, bless it) and I've already been through the pain in the arse of getting Spring.Net working under Mono. Well, just Spring.Core really, but that's the only bit I'm interested in so fuck it, whatever. I'm using Mono 2.8 which gives me .Net 4 functionality. If you're interested in getting Mono/XSP working on Ubuntu or Fedora Linux then I highly recommend this page which has a comprehensive install script. I did have to do a little bit of make check; make install afterwards to bring my MonoDevelop stuff up to date, but aside from that it went smoothly (although it took about 45 minutes on shard!).

So, I have .Net 4 capability, a working Spring.Net/Common.Logging build, and that script gave me XSP version 4. I've never used XSP before but there are quite a few good pages on it, even if they do appear to be from 2006. Hell, I can't even remember if we had Google back in 2006. There followed a couple of bumps of a) remembering that I had to set up the custom http handler part of it in the web.config, and b) my .Net solution in MonoDevelop won't make an ASP.Net web application project that uses anything above version 3.5 for reasons best known to itself, which stops you referencing the projects directly from the web host. However, XSP and Mono are more than happy with it, so I made an empty library project that referenced the projects and now have a pre-XSP step that copies the latest DLLs into the web host application.

Alright. Now I have a working application. Almost. This happened:

This kept me going for over an hour, having to break bits of code by design in order to get a sensible answer out of Mono since I couldn't attach a debugger to it.

The problem occurred whenever the Store behaviour was called. Now it turns out that this behaviour happens to be the only one which refuses to do anything if the user isn't authenticated. Like so:

When the behaviour returns false, that signals that the command that is being delivered on the message bus has not been fully satisfied. So therefore it will move on to the next listener it has. Here is the delivery code:

Now what I couldn't fathom, is why this somehow breaks in Mono but runs fine under Windows. The bug is essentially implying that there is a listener in the collection which is null. I was feeling paranoid about this and so I made sure that there was a null check on the Add routine in the message bus.

Ok, so. All good, yeah?

No. Still fucked. In desperation, I added some code to show the listeners collection every time a message was being delivered. The result?

There were 2K of listeners in each of my two message buses listener collections. WTF?

The listener collection is pretty straightforward:

So just a ConcurrentBag of my interface type. That's absolutely fine and to my knowledge I had no reason to believe that it would spawn extra capacity.

I ran that particular test with an unmodified listeners collection on my Windows build and received the following result:

Which is correct behaviour. WTF?!? It turns out that there appears to be different behaviour for the System.Collections.Concurrent.ConcurrentBag in Microsoft.Net 4.0 and in Mono 2.8, where the Microsoft version enumerates correctly based on number of added items, and the Mono version seems to enumerate over an extended capacity.

Given that there is little practical difference in contention handling between locking on a System.Collections.Generic.List and using a ConcurrentBag, I started to use a List as it doesn't have the same retarded behaviour.

Yay! Working application... And now when running the upload tester...

Which gives me one of these...


At which point it was time for sleepz.

Friday, 8 June 2012

Sunday, 3 June 2012

How to Stop .Net 4 Client Profile being The Default in Visual Studio and Cocking Everything Up

The .Net 4 Client Profile project target in Visual Studio happens to be, about every couple of weeks or so, the bane of my fucking life. I will make a project, forgetting that it is the default for some of the templates and proceed to spend ten minutes wondering why the hell I can't find any references. This annoys the hell out of me and I have not found a way to back out of it being installed as a default for many types of project (listed on this msdn page)

At the behest of a work mate, I'm going to write this short guide on how to change the default for these projects.

In this example, I am going to change the default project target for the Console Application project type.

1. Find the right folder

I don't know where you have Visual Studio installed, but mine is at "C:\Program Files (x86)\Microsoft Visual Studio 10.0"

Further, you need to find where it keeps the project templates.

Should be in: {visual studio directory}\Common7\IDE\ProjectTemplates\CSharp\Windows\1033 (where 1033 is your language region)

2. Open up the archive

Actually, best bet is just to extract it somewhere

3. Edit the file "consoleapplication.csproj"

Here we go. In the top PropertyGroup section. Here's the bastard to remove:

  $if$ ($targetframeworkversion$ >= 4.0)

Scrub that motherfucker like it ain't no thang.

4. Save, replace in archive, etc, etc


5. Wondering why this didn't work?

Because of reasons that I cannot fathom, there is a cache of the project templates.

6. Copy the files into the cache

They will need to go into a folder called "", which will be found at: {visual studio directory}\Common7\IDE\ProjectTemplatesCache\CSharp\Windows\1033


There... Hopefully that feels better. Thanks for wasting my time, Microsoft.