I experimented with Google's new service,
Google Transit.
It suggested this route for traveling from
my home to my work:
Begin by walking
1 Start at 4XXX 13th Ave S
2 Go to Airport Way S & S Industrial Way (takes about 7 mins)
Take the King County Metro 131 (Direction: NORTH)
3 7:17pm leave from Airport Way S & S Industrial Way
4 7:24pm arrive at 4th Ave S & S Jackson St
End by walking
5 Go to 315 5th Ave S (takes about 2 mins)
This fails badly in two respects.
First, four bus routes run along 15th Avenue S,
two blocks east of my house:
the 39,
the 32,
the 36,
and the 60.
The 39 drops me one block from work at 4th & Jackson.
The 60 leaves me at 12th & Jackson.
The 36 only runs along 15th after 7pm;
earlier than that, I a 10-minute walk to Beacon Ave.
And the 32 is an express bus that only runs at rush hour.
Second, it suggests that it's a seven-minute walk to
Airport Way S & S Industrial Way.
Actually, it's a two-mile walk, because I-5 and the railroad are in the
way. You have the unpleasant choices of walking north to Spokane Street
and climbing down an endless set of stairs at the freeway onramp,
or south to the Lucile St bridge. And even if there were a direct route,
it would take at least 10 minutes to walk down there.
That said, it integrates very nicely with Google Maps.
The Google Transit page links to
Metro Trip Planner,
which does a better job. Their disambiguation of addresses sucks, however.
Try entering 5th & Jackson. It suggests a short list, starting with
5TH AVE S & S JACKSON ST (in SEATTLE). However, if you actually type
that address into the main page, it offers you a long list of suggestions.
In other words, it can't consume its own output.
I ran into a problem installing some COM+ components today. The installer
was using Regsvcs.exe
to register each COM+ component. I noticed after a while that the installer
wasn't making any progress and that my dual-proc system was stuck at 50%
CPU utilization. I attached a debugger to the offending process, regsvcs,
and found that it was stuck in the following infinite loop
(disassembly courtesy of Reflector):
internal void System.EnterpriseServices.CatalogSync.Wait()
{
if (this._set)
{
RegistryKey key1
= Registry.LocalMachine.OpenSubKey("SOFTWARE\\Classes\\CLSID");
while (true)
{
int num1 = (int) key1.GetValue("CLBVersion", 0);
if (num1 != this._version)
{
break;
}
Thread.Sleep(0);
}
this._set = false;
}
}
There are two severe problems with this code.
-
The loop should time out. There must be some reasonable limit after
which you can incontrovertibly say that something must have gone wrong,
and throw an exception. There has to be some way to terminate a loop.
-
Never use Sleep(0) in a loop. Sleep(0) yields the processor only
if there's a runnable thread. If there isn't, Sleep(0) will return
immediately. If the code is sitting in a tight loop, the net effect is
that it will maximize the CPU until the thread's quantum is exhausted.
There are no other runnable threads, so the scheduler immediately
starts this thread again. This code will run until your CPU burns out.
(And, yes, I have committed both of these sins in shipping code. Why do you ask?)
I don't know what the calling code is doing or why CLBVersion isn't
being altered by some other thread or process. I had to use RegEdit to
modify this value to get the loop to terminate, whereupon RegSvcs
immediately did its work and terminated. And then it started all over
again, with the next invocation of RegSvcs on another COM+ component.
I don't know if the components are really installed properly. I had to
leave at that point.
My colleague, Greg, and I spent all day debugging a build break in
some unit tests that exercise a webservice interface in legacy .NET 1.1 code.
Last night, the tests stopped working on our
CruiseControl.NET
build server. We couldn't understand it. The tests had been working for
months. Now we were getting timeouts in SOAP. The tests essentially
mock
a SOAP service using the soap.inproc transport and a stub
implementation that signaled an event to acknowledge a method being called.
The only thing that had changed in the code tree was that another
colleague, Pavel, had discovered that two of our .csproj files somehow
shared the same GUID, and had repaired that. But that could hardly have any
effect on the WSE2 runtime. Could it?
Turns out that it was the cause of the break.
NAnt 0.85 rc2 and rc3 silently failed to build the
NUnit assembly because of the duplicated GUIDs. The assembly was not
getting propagated to the directory where all the other NUnit assemblies
are placed. The CC.NET task that ran the tests never noticed the missing
assembly because the test was couched in terms of *.NUnit.dll. And we
never noticed that the test hadn't been run in months because we have ~20
such NUnit assemblies, and the NUnit summary output goes on for several
screens in CC.NET.
Morals of the story
-
Use NAnt 0.85 rc4, which
detects the GUID collision and treats it as a fatal error.
-
Create .csproj files through the IDE, not by taking an existing file
and hacking on it. (At least, that's we assume happened.)
-
Assumptions can bite you. We assumed that the code was being run all
along, so it took us several hours to draw the connection between
Pavel's checkin and the failing NUnit assembly.
-
Don't mock a webservice by implementing a dummy SoapReceiver,
hauling in the WSE runtime and a boatload of non-determinism.
(Instead, make fun of its dress sense.)
For our newer code, we've been taking an approach
like this,
using partial classes and Rhino Mocks.
-
We have also taken to including our test fixtures in the same
assemblies as the code they test. I have mixed feelings about this:
it offends my sensibilities to have all this test code compiled into
production code. But it would certainly have been hard to miss the
build break in production code.