07 November 2012
Cooperative Thread Abort in .NET
Did you know that .NET uses a cooperative thread abort mechanism?
As someone coming from a C++ background I always thought that killing a thread is bad behavior and should be prevented at all costs. When you terminate a Win32 thread it can interrupt the thread in any state at every machine instruction so it may leave corrupted data structures behind.
A .NET thread cannot be terminated. Instead you can abort it. This is not just a naming issue, it is indeed a different behavior. If you call Abort() on a thread it will throw a ThreadAbortException in the aborted thread. All active catch and finally blocks will be executed before the thread gets terminated eventually. In theory, this allows the thread to do a proper cleanup. In reality this works only if every line of code is programmed in a way that it can handle a ThreadAbortException
in a proper way. And the first time you call 3rd-party code not under your control you are doomed.
Too make the situation more complex there are situations where throwing the ThreadAbortException is delayed. In versions prior to .NET 4.5 this was poorly documented but in the brand new documentation of the Thread.Abort method is very explicit about this. A thread cannot be aborted inside a catch or finally block or a static constructor (and probably not the initialization of static fields also) or any other constrained execution region.
Why is this important to you?
Well, if you are working in an ASP.NET/IIS environment the framework itself will call Abort() on threads which are executing too long. In this way the IIS can heal itself if some requests hit bad blocking code like endless loops, deadlocks or waiting on external requests. But if you were unlucky enough to implement your blocking code inside static constructors, catch or finally blocks your requests will hang forever in your worker process. It will look like the httpRuntime executionTimeout is not working and only a iisreset will cure the situation.
Download the CooperativeThreadAbortDemo sample application.
27 September 2012
Embed Url Links in TeamCity Build Logs
But it seams that there is no way to include links in TeamCity build logs. TeamCity correctly escapes all the output from test and build tools so it is not possible to get some html into the log. So I investigated TeamCity extension points. Writing a complete custom html report seemed to be overkill because the test reporting tab worked really well. Writing a UI plugin means to learn Java, JSP and so on and as a .NET company we don't want to fumble around with the Java technology stack. But as a web company we know how to hack javascript ;-)
There is already a TeamCity plugin called StaticUIExtensions that allows you to embedd static html fragments in TeamCity pages. And because a script tag is a valid html fragment we could inject javascript into TeamCity. So I wrote a few lines of javascript that scan the dom for urls and transforms them into links. With this technique you get clickable links in all the build logs.
What you need to do:
- Install StaticUIExtensions
- On your TeamCity server, open your "server\config\_static_ui_extensions" folder
- Open static-ui-extensions.xml
- Add a new rule that inserts "show-link.html" into every page that starts with "viewLog.html"
<rule html-file="show-link.html" place-id="BEFORE_CONTENT"> <url starts="viewLog.html" /> </rule> - Create a new file "show-link.html" with this content:
<script> (function ($) { var regex = /url\((.*)\)/g function createLinksFromUrls() { $("div .fullStacktrace, div .msg").each(function () { var div = $(this); var oldHtml = div.html(); var newHtml = oldHtml.replace(regex, "<a href='$1' target='_blank'>$1</a>"); if (oldHtml !== newHtml) div.html(newHtml); }); } $(document).ready(createLinksFromUrls); $(document).click(function () { window.setTimeout(createLinksFromUrls, 50); window.setTimeout(createLinksFromUrls, 100); window.setTimeout(createLinksFromUrls, 500); }); })(window.jQuery);
</script>
Voila, Mission completed.
10 August 2012
"Right" vs "Simple"
MIT
- Simplicity
- The design must be simple, both in implementation and interface. It is more important for the interface to be simple than the implementation.
- Correctness
- Correctness-the design must be correct in all observable aspects. Incorrectness is simply not allowed.
- Consistency
- The design must not be inconsistent. A design is allowed to be slightly less simple and less complete to avoid inconsistency. Consistency is as important as correctness.
- Completeness
- The design must cover as many important situations as is practical. All reasonably expected cases must be covered. Simplicity is not allowed to overly reduce completeness.
New Jersey
- Simplicity
- The design must be simple, both in implementation and interface. It is more important for the implementation to be simple than the interface. Simplicity is the most important consideration in a design.
- Correctness
- The design must be correct in all observable aspects. It is slightly better to be simple than correct.
- Consistency
- The design must not be overly inconsistent. Consistency can be sacrificed for simplicity in some cases, but it is better to drop those parts of the design that deal with less common circumstances than to introduce either implementational complexity or inconsistency.
- Completeness
- The design must cover as many important situations as is practical. All reasonably expected cases should be covered. Completeness can be sacrificed in favor of any other quality. In fact, completeness must sacrificed whenever implementation simplicity is jeopardized. Consistency can be sacrificed to achieve completeness if simplicity is retained; especially worthless is consistency of interface.
17 June 2012
Visualizing a code repository with Bubble Charts and Circle Packing
Warum eigentlich ...
Die Technik
29 March 2012
HTML5 without warnings in Visual Studio
Today I was annoyed about warnings that Visual Studio shows when editing an html5 file. Example: VS expects a type attribute inside the script tag but html5 doesn't require it anymore (because it defaults to javascript).
When opening the context menu I noticed the "Formatting and Validation" item and opened it:
Choosing "HTML5" as a target removes all those annoying wrong warnings :-)
19 January 2012
The best fellow employee ...
... is someone that you can criticize without pissing him off. The same should be true the other way round. I'm glad that I'm working for an exceptional company where nearly everyone has this attitude.
27 November 2011
Speed up your build with UseHardlinksIfPossible
MsBuild 4.0 added the new attribute "UseHardlinksIfPossible" to the Copy task. Using Hardlinks makes your build faster because less IO operations and disk space is needed (= better usage of file system cache). What's best is that this new option is already be used by the standard .net build system! But Microsoft decided to turn them off by default.
After searching a little bit in the c# target files I found out how to turn this feature globally on and my build was 20% faster than before. And if you have big builds with more than a hundred projects this counts!
So here comes the way to turn on hard linking in your build. First, this works only with NTFS. Second you have to explicitly set the ToolsVersion to 4.0. You can do this with a command line argument (msbuild /tv:4.0) or inside the project file (<Project DefaultTargets="Build" ToolsVersion="4.0" ...).
Then you have to override the following properties with a value of "True":
- CreateHardLinksForCopyFilesToOutputDirectoryIfPossible
- CreateHardLinksForCopyAdditionalFilesIfPossible
- CreateHardLinksForCopyLocalIfPossible
- CreateHardLinksForPublishFilesIfPossible
Use command line properties (msbuild /p:CreateHardLinksForCopyLocalIfPossible=true) to override them for all projects in one build. Or you can create a little startup build file that collects all projects and set the properties in one place. Here is mine:
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<PropertyGroup>
<Include>**\*.csproj</Include>
<Exclude>_build\**\*.csproj</Exclude>
<CreateHardLinksIfPossible>true</CreateHardLinksIfPossible>
</PropertyGroup>
<ItemGroup>
<ProjectFiles Include="$(Include)" Exclude="$(Exclude)"/>
</ItemGroup>
<Target Name="Build" >
<MSBuild Projects="@(ProjectFiles)" Targets="Build" BuildInParallel="True" ToolsVersion="4.0"
Properties="Configuration=$(Configuration);
BuildInParallel=True;
CreateHardLinksForCopyFilesToOutputDirectoryIfPossible=$(CreateHardLinksIfPossible);
CreateHardLinksForCopyAdditionalFilesIfPossible=$(CreateHardLinksIfPossible);
CreateHardLinksForCopyLocalIfPossible=$(CreateHardLinksIfPossible);
CreateHardLinksForPublishFilesIfPossible=$(CreateHardLinksIfPossible);
" />
</Target>
</Project>

