Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,590
|
Comments: 51,223
Privacy Policy · Terms
filter by tags archive
time to read 5 min | 919 words

[I wrote this several days ago]

The hour is 03:15 AM, and I’m sitting here satisfied. Another bug eliminated, another enemy conquered. And this one is a tricky one.
I’ve created an application that loads Caudill’s TreeListView as its main UI. Now, my problem was that after I created about 50% of the application, I decided to work on the start-up data load, and then the application started to get nasty.
An IndexOutOfBoundException charged out of nowhere, directly into my flanks. I was determined, however, and after donning my debugging armor counter-attacked.

First, I traced the application to where it barfed, which wasn’t nice, it uses threads so it won’t freeze (lot of network action).
Eventually I managed to track the error to a method which was adding items to the TreeListView.
Now, that was strange, because the exact same code was working just a few minutes ago when I was using it to insert items after the application loaded.
I commented the line that called the insertion on start-up, and… woila – everything works!

Then I knew that it wasn’t going to be nice. Nevertheless, I set to track the path of the enemy’s army… err program execution, I mean.
I found out that I inserted items into the TreeListView before I added columns to it. Aha, I thought, now I got it! Fixed this, compile and run… but IndexOutOfBound has managed to sneak behind me again, leaving me with no other option but following the entire execution path of the program when I did manage to insert the items (on normal program execution).

Tired and panting, I finished that battle, but I felt victorious, I used the campaign to refactor my forces organization, and I was certain that they would withstand any attack. But over-confidence was my failing, for as I tried once more to head for the territories I desired. I’ve tracked the traitor deep into the enemy lines, until I could no longer follow without risking the dreaded disassembly. But I thought I’d it now, I managed to reinterduce inserting the items without adding columns, so I was confident that all will be fine.

The exception caught me unaware, leaving me frustrated and screaming.
Time to regroup and do some thinking, I thought, so I commented the insertion on startup and tried invading again. But I stopped short, afraid, for there was no opposition this route.
Now I knew that I’d a spy on my side, for something was very wrong.
Hungry for blood, I attempted to throw confusion in the enemy’s lines and checked the startup data.
I wondered… could it be… but the changes were made in the application, shouldn’t it betray me then?
Change the startup data to match exactly to that created in the application and test.
Success, I’d a beachhead on the enemy’s front.
But it was still too early to get cocky; I tried to change the startup data again, and checked what this might cause.
Treason! Mayhem! The exception only struck if I tried to insert the most important items.
But how could the enemy reveal that? The only difference I could see that some of the items were selected (they were created and then selected on previous, more successful campaigns).
Impossible, for such a small change to create such drastic measurements! Yet I’d seen it with my own eyes.

Item. Checked = Group. Selected;

This was the traitor.

If Group.Selected was true, then I was for an unpleasant surprise trying to insert.
But why should it make any difference?
I tested, commenting this line and sending scouts ahead. They returned with glowing eyes, talking about a rich land, if only I could overcome the treason in my own camp…
I could not get rid of the traitor; he was too dear to me, so I sent him to the front, after the insertion occurred.
And a miracle occurred, my surprised attack was successful, and I had scored the enemy lines in many fronts.
But there was still the matter of the traitor…
I sent him to the front with a small unit, and he excelled, and so I slowly enlarged his command until I finally had so sent him a lieutenant – and then disaster struck.
Again a flank attack, directly at my weak spot. And now I’ve located the real tratior.
He was a small routine, meant to handle ItemCheck called from  the TreeListView, the problem with him was that he used this code:

Group add_grp = Messages.Items[e.Index].Tag as Group;

Apparently, TreeListView (and ListView, its base) first call the ItemCheck delegate when they get an item with Checked = true and only afterward they add the item to their Item list.
So whenever this routine was called, it would generate an IndexOutOfBoundException, I couldn’t trace it to its real location using StackTrace because I’m using threads to create a responsive UI.

Conclusions:

  • Always have a UnhandledException and ThreadException handlers, that could’ve saved me a long time, I just tested it, and it would’ve give me the real stack trace of the error which would’ve enabled me to solve this in a few minutes.
  • I would’ve never caught on to this bug if I wasn’t trying to repreduce the problem and settle on the workaround.
  • Debugging multi-threading code is fun as an excrise for the bored mind.
  • The only reason that I got this exception from the main thread was that I was using Invoke to update the UI, otherwise, I was into more trouble.
  • That was a lovely way to spend the night, thank you very much.
time to read 2 min | 397 words

Well, it was too early to brag about open software. I always supported the idea that having the code is nice, but making any useful changes to it is hard.
The reason is simple about the amount of time you can invest in the project. If we take dasBlog as an example, it support FreeTextBox, which is a rich text box editor that output HTML.
All is good, as long as you remain in Internet Explorer. I’ve recently moved to Firefox, just to try the platform, and naturally I thought to use it to post to my blog.
The problem is that while I can post, I can only do it from a normal textbox.

This is acceptable behaviour, since the version of FreeTextBox can’t display on Mozilla’s browsers, it downgrade nicely to a simple textbox.
[Oh, for the days when IE had a natural htmlbox. Netscape/Mozilla would’ve’d to follow, and we had this without the contortions that we use now.]
Now, this is a good and acceptable behaviour on the side of dasBlog, but it’s not acceptable to me.
There is a new version of FreeTextBox that does both IE & Mozilla (including Netscape & FireFox) so I figured what the heck, I can easily add the new textbox and be done with in a few minutes.
Unfortantely, FreeTextBox 2.0 is not code compatible with the version that dasBlog uses. This mean that I’ve to do much more than merely drop the new version.
This means that I’ve to change the code, and this means that I’ve to grok it. Now, dasBlog isn’t that big, but it still have over 45 Kloc thousnads lines of C# code as well as another 25 + thousands lines of html/aspx code.

That is quite a bit of code to grok. In essense, unless I’m willing to dedicate two to three days some time to completely understand what dasBlog does, I won’t be able to touch the code at all.
I sent an email to newtelligence, the company that maitain the code, about it. I think it should be about an hour change for some one who knows the code vs four days for me.

It doesn’t help that dasBlog doesn’t has any documentation regarding its makeup, I’ve to delve into the code to see what it does, and I’m not feeling really up to it right now.

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. RavenDB 7.1 (7):
    11 Jul 2025 - The Gen AI release
  2. Production postmorterm (2):
    11 Jun 2025 - The rookie server's untimely promotion
  3. Webinar (7):
    05 Jun 2025 - Think inside the database
  4. Recording (16):
    29 May 2025 - RavenDB's Upcoming Optimizations Deep Dive
  5. RavenDB News (2):
    02 May 2025 - May 2025
View all series

Syndication

Main feed ... ...
Comments feed   ... ...
}