“Prodigy” doesn’t mean what I thought

by acha11 28. May 2010 00:53

Romans were particularly concerned by ‘prodigies’, odd things and events which seemed to be signs of the gods’ communication. A prodigy might be a deformed child at birth, a mole (reportedly) with teeth or an apparent shower of blood from heaven. Soothsayers and a priest stood by to list prodigies and interpret them.

- p. 299, The Classical World, Robin Lane Fox

Wiktionary has prodigy coming via Middle English prodige (“portent”), from Latin prodigium (“omen, portent, prophetic sign”).

Because of the phrase “child prodigy”, I grew up assuming that “prodigy” meant “gifted person”. Later, I think I must have seen it used in the sense of “prodigious feat”, which probably reinforced my belief.

It’s a neat little revelation. Normally, a gifted musician puts me in mind of the thousands of hours of work they’ve spent polishing whatever natural talent they began with. But the concept of “prodigy” jolts me into a world-view in which a musician’s talent can only be understood as an omen from the gods.

Also, the idea that a prodigy can be either a blessing or a curse for the messenger sets me reeling a bit.

“Messenger” is the wrong word, I think. If there’s a consciousness involved (a deformed child, say), then they’re more the slate on which the message is written than an active messenger; even a phenomenon (e.g. blood falling as rain) can serve as a prodigy.

I like the name “The Prodigy” a lot more now, even though this article says it’s taken from the Moog Prodigy synthesizer.

Tags:

SQL Server Reporting Services 2005 and 2008 – cancelling a long-running report causes the next “View report” to hang the UI until the original finishes

by acha11 26. January 2010 19:42

Sorry for the repost; this post made it live (and into my Google Reader history), and then mysteriously disappeared from my BlogEngine.NET installation on GoDaddy. I suspect somebody quietly restored my database from backup without 'fessing up. Anyway:

This issue’s really annoying. It’ll drive our users nuts. Defining the issue precisely was pretty interesting, though. I haven’t found the right set of google search terms to find others who’ve run into or analysed this problem yet; hopefully this will help someone else.

The background

SSRS is a reporting framework from Microsoft.

  • SSRS WinForms ReportViewer sits inside our WinForms client-side application.
  • It talks via Web Services to the SSRS middle tier hosted in IIS on our app servers.
  • SSRS middle tier stores report metadata and in-flight request information in databases in SQL Server (ReportServer and ReportServerTempDb)
  • SSRS middle tier generates reports off our reporting schema in a (separate) SQL Server database.

The scenario

You’re using SQL Server Reporting Services 2005 or 2008. You’re displaying reports by hosting the SSRS WinForms ReportViewer control inside your UI.

You launch a long-running report, and the “Report is being generated” message is displayed.

image

You realise you chose the wrong set of report parameters, so you press the red “Stop” button to cancel report generation:

image

Note that at this point, the long-running SQL Server call to get the report data is still running on the server-side.

You amend your report parameters and press “View report” again:

image

The eagle-eyed will notice that nothing’s changed. The user is given no feedback that the second "View report” command is being processed. Even worse, the UI thread is actually completely blocked, waiting for a call to the SSRS server to complete.

Investigation

How can this be happening? The ReportViewer seems to do the server call to get report data on a background thread, so that it can give us the nice hourglass from the first screenshot above, and yet the second call’s blocking the UI thread horribly.

If we re-run the test and pause the debugger while the UI thread’s blocked after the second “View report” command’s issued, we see the following threads:

image

And the main (UI) thread has the following call stack:

  • [Managed to Native Transition]   
  • System.dll!System.Net.Sockets.Socket.Receive(byte[] buffer = {byte[4096]}, int offset = 0, int size, System.Net.Sockets.SocketFlags socketFlags = None, out System.Net.Sockets.SocketError errorCode = Success) + 0xc4 bytes   
  • System.dll!System.Net.Sockets.Socket.Receive(byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags socketFlags) + 0x20 bytes   
  • System.dll!System.Net.Sockets.NetworkStream.Read(byte[] buffer, int offset, int size) + 0x84 bytes   
  • System.dll!System.Net.PooledStream.Read(byte[] buffer, int offset, int size) + 0x1b bytes   
  • System.dll!System.Net.Connection.SyncRead(System.Net.HttpWebRequest request = {System.Net.HttpWebRequest}, bool userRetrievedStream = true, bool probeRead = true) + 0x12a bytes   
  • System.dll!System.Net.Connection.PollAndRead(System.Net.HttpWebRequest request, bool userRetrievedStream) + 0x5a bytes   
  • System.dll!System.Net.ConnectStream.PollAndRead(bool userRetrievedStream) + 0x1b bytes   
  • System.dll!System.Net.HttpWebRequest.EndWriteHeaders(bool async) + 0xa2 bytes   
  • System.dll!System.Net.HttpWebRequest.WriteHeadersCallback(System.Net.WebExceptionStatus errorStatus, System.Net.ConnectStream stream = {System.Net.ConnectStream}, bool async) + 0x16 bytes   
  • System.dll!System.Net.ConnectStream.WriteHeaders(bool async) + 0x2d1 bytes   
  • System.dll!System.Net.HttpWebRequest.EndSubmitRequest() + 0x82 bytes   
  • System.dll!System.Net.HttpWebRequest.SetRequestSubmitDone(System.Net.ConnectStream submitStream) + 0xf7 bytes   
  • System.dll!System.Net.Connection.CompleteConnection(bool async, System.Net.HttpWebRequest request = {System.Net.HttpWebRequest}) + 0x158 bytes   
  • System.dll!System.Net.Connection.CompleteStartConnection(bool async, System.Net.HttpWebRequest httpWebRequest) + 0x177 bytes   
  • System.dll!System.Net.Connection.CompleteStartRequest(bool onSubmitThread, System.Net.HttpWebRequest request = {System.Net.HttpWebRequest}, System.Net.TriState needReConnect = True) + 0x9a bytes   
  • System.dll!System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest request = {System.Net.HttpWebRequest}) + 0x293 bytes   
  • System.dll!System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest request = {System.Net.HttpWebRequest}, string connName = "S>System.Net.NegotiateClient/25/S") + 0x7c bytes   
  • System.dll!System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint servicePoint) + 0xf9 bytes   
  • System.dll!System.Net.HttpWebRequest.GetResponse() + 0x270 bytes   
  • System.Web.Services.dll!System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(System.Net.WebRequest request) + 0xd5 bytes   
  • System.Web.Services.dll!System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(System.Net.WebRequest request) + 0x5 bytes   
  • Microsoft.ReportViewer.Common.dll!Microsoft.SqlServer.ReportingServices2005.Execution.RSExecutionConnection.GetWebResponse(System.Net.WebRequest request) + 0xe bytes   
  • Microsoft.ReportViewer.WinForms.dll!Microsoft.Reporting.WinForms.ServerReportSoapProxy.GetWebResponse(System.Net.WebRequest request) + 0x10 bytes   
  • System.Web.Services.dll!System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(string methodName, object[] parameters) + 0xad bytes   
  • Microsoft.ReportViewer.Common.dll!Microsoft.SqlServer.ReportingServices2005.Execution.ReportExecutionService.SetExecutionParameters(Microsoft.SqlServer.ReportingServices2005.Execution.ParameterValue[] Parameters, string ParameterLanguage) + 0x42 bytes   
  • Microsoft.ReportViewer.Common.dll!Microsoft.SqlServer.ReportingServices2005.Execution.RSExecutionConnection.SetExecutionParameters(Microsoft.SqlServer.ReportingServices2005.Execution.ParameterValue[] Parameters, string ParameterLanguage) + 0x42 bytes   
  • Microsoft.ReportViewer.WinForms.dll!Microsoft.Reporting.WinForms.ServerReport.SetParameters(System.Collections.Generic.IEnumerable<Microsoft.Reporting.WinForms.ReportParameter> parameters) + 0x2a1 bytes   
  • Microsoft.ReportViewer.WinForms.dll!Microsoft.Reporting.WinForms.RSParams.SaveControlValuesToReport() + 0x309 bytes   
  • Microsoft.ReportViewer.WinForms.dll!Microsoft.Reporting.WinForms.RSParams.viewReport_Click(object sender, System.EventArgs e) + 0x57 bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Control.OnClick(System.EventArgs e) + 0x70 bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Button.OnClick(System.EventArgs e) + 0x4a bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Button.OnMouseUp(System.Windows.Forms.MouseEventArgs mevent = {X = 44 Y = 3 Button = Left}) + 0xac bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Control.WmMouseUp(ref System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons button, int clicks) + 0x28f bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x885 bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.ButtonBase.WndProc(ref System.Windows.Forms.Message m) + 0x127 bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Button.WndProc(ref System.Windows.Forms.Message m) + 0x20 bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x10 bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int msg = 514, System.IntPtr wparam, System.IntPtr lparam) + 0x5a bytes   
  • [Native to Managed Transition]   
  • [Managed to Native Transition]   
  • System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason = -1, int pvLoopData = 0) + 0x24e bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) + 0x177 bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 bytes   
  • System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm) + 0x31 bytes   
  • >    WindowsFormsApplication4.exe!WindowsFormsApplication4.Program.Main() Line 20 + 0x1d bytes    C#
  • [Native to Managed Transition]   
  • [Managed to Native Transition]   
  • mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x3a bytes   
  • Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2b bytes   
  • mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes   
  • mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes   
  • mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   

From the bolded lines, reading from the bottom up, we can see:

  • this thread’s pumping messages (RunMessageLoop), so it’s likely to be a UI thread;
  • it’s handling a button click on the ViewReport button (OnClick and viewReport_Click), so it is likely to be the blocked UI thread that’s causing us grief;
  • it’s making a synchronous Web Services call to the Report Server (via a proxy) to a method called “SetExecutionParameters”

So in reality, SSRS is actually making at least two Web Services calls to the Report Server. The first is a UI-blocking synchronous call to SetExecutionParameters, and the second is an asynchronous call to do the actual report generation.

Because the first click on “View Report” didn’t block the UI and in fact jumped straight to the friendly hourglass UI mode, we can infer that SetExecutionParameters either wasn’t called first time through, or it was called and was so fast that we didn’t notice the blocking.

While the UI’s blocked, let’s go the SQL Server and get a list of locks that processes are waiting on in either of our SSRS databases:

select *
from sys.dm_tran_locks  l
where resource_type = 'KEY' and request_status <> 'GRANT'
order by resource_database_id, request_owner_id, request_request_id

image

So, somebody’s waiting for a LOCK on a KEY resource (roughly, a particular value in an index) with resource_associated_entity_id = 72057594038386688. What does that number correspond to?

image

Okay, somebody’s waiting on a lock on a KEY value in the SessionLock table in ReportServerTempDb. Sure looks as if there’s a session-level lock, and the first report generation server call is holding that lock while the second “SetExecutionParameters” request waits for it to complete. Because (and this is the whole point of supporting cancellation) that first generation call is taking a very long time to complete, the user’s going to be stuck waiting for a very long time, with the UI completely hung, before the second request is cancellable and actually commences the real work of generating report results.

This sucks.

Analysis

While it looks like the SSRS WinForms ReportViewer control has a nice asynchronous design that avoids blocking the UI thread, it still blocks in exactly the situation where it’s most irritating.

  • SSRS has a SessionLock which serializes certain operations at a per-Session level.
  • SetExecutionParameters and report generation both require the SessionLock, so can’t run concurrently for a given session.
  • The SSRS team didn’t find and implement a reliable way to cancel an in-flight request before processing a second request.
  • So if a long-running report generation process kicks off, any subsequent requests from that session will have to wait until the first request dies or completes.
  • SSRS backgrounds the report generation call. This is good; users get feedback that something’s happening, and the UI thread’s not blocked, so the rest of the application is still usable.
  • SSRS mistakenly assumes that “SetExecutionParameters” will never be long-running, so doesn’t background it. This assumption is wrong, because it can be blocked by an earlier report generation call that’s still running. When this happens, the UI thread’s blocked, and the client’s application hangs completely. User experience sucks.

Workarounds

  1. Do nothing.
  2. Write your own ReportViewer alternative that backgrounds all potentially long-running server calls. A lot of work, I know.
  3. Hide the Stop button (set the ShowStopButton property to false on the ReportViewer instance) and provide your own Stop button outside of the control. This external stop button then resets or even re-instantiates the control completely, causing a new user session to be created, so there’s no contention on SessionLock, so the user experience is improved. ReportViewer property values that were previously set in the designer will have to be re-applied. Horrible, I know.
  4. Hook the ReportViewer’s RenderingComplete event. Check RenderingCompleteEventArgs for an exception whose message contains “the operation was canceled”. If that exception’s present, then assume the user clicked “Stop”. Re-create or Reset() the Report viewer. Horrible, I know.

We’re likely to go with option 4 at this point.

Tags:

I stumbled across some brilliant writing this morning

by acha11 13. January 2010 13:41

It's a tutorial page for a strategy game set in hell. I haven't played the game, but the tutorial is good enough that i might have to try it. Or get Pat to try it and let me know if it’s any good.

The premise is that your "tutor" is a prince of hell, and he's an articulate but hate-filled thing-that-should-not-be who's completely underwhelmed by your mental prowess.

So he says wonderful, horrible things like:

   "and yet... i need... your help. When i said "need", i chewed off a small piece of my lip. When i said "help", i vomited. Consuming it calmed me."

and

   "my tears of mirth track through my nasal vents to form a foamy broth that i will enjoy while you return to the map."

and

   "we will attempt to provoke moloch. more than once, he has refused my broths."

and (after explaining what "clockwise" means)

   "my appendages curl and uncurl as i picture your vacant stare".

My personal favourite is “More than once, he has refused my broths.” I’m just waiting for the opportunity to slip it in to conversation next time we’re discussing someone who’s made a habit of irritating me :-)

 

Tags:

Mandelbrot scaffolding

by acha11 2. January 2010 05:06

I’ve added a new feature to my Mandelbrot renderer.

Quick refresher: points are in the Mandelbrot set if, no matter how many times you apply a simple transform, they never escape to infinity.

The new feature shows the path taken while iterating a specific point.

Robot lollipop

This screenshot shows an ever-decreasing spiral. The start of the spiral is pretty close to the centre of the image. That’s point (0, 0) in the plane. The path jumps from there to the actual point being rendered, which I’m guessing is about (0.5, 0.5). From there, as we keep iterating, the point describes a shrinking spiral, never escaping to infinity.

Mandelbrot_Path_Plot_1

Spirograph

The path taken for this point (a bit up and left of the previous one) is a bit more interesting; it’s still describing a shrinking spiral, but the rate of shrink is a lot lower, and the angle is a lot tighter.

Mandelbrot_Path_Plot_2

Corporate logo #3414

And this path’s more interesting again – it’s noticeably asymmetrical.

Mandelbrot_Path_Plot_3

Qix 2010

This is the path taken by a point in the left-hand circle – these tend to be a lot less beautiful looking as screenshots, but seen live, the trajectories (which shift and reconfigure as you drag the mouse around) sweep between different “stable”, “aligned” configurations in a really interesting way. I need to hook up some video capture again.

Mandelbrot_Path_Plot_5

Here’s an example of a stable configuration that cycles around four nodes (even a long way outside the set proper) without ever actually escaping. Note that this isn’t a precise cycle – each iteration seems to be slightly different to the last.

Mandelbrot_Path_Plot_6

Escape

None of the five points so far have escaped to infinity, so their corresponding pixel is rendered white, and the path in the above shots is shown in grey. This screenshot shows what happens when a point does escape. The path looks a lot more unordered (although there is some structure), and it ultimately disappears off the top of the screen (well North of (0, 2)).

 

Mandelbrot_Path_Plot_4

Tags:

We built a town called “Wisdom”…

by acha11 15. December 2009 15:36

on a SUPERVOLCANO.

This is entry #4314 in the series “first lines of choruses of songs Andrew makes up in his head on the train.” This is a shouty chorus.

Thanks for your kind attention.

Tags:

Raymond Chen sums up software development; we can all go home

by acha11 14. November 2009 16:40

A beautiful thing to say

A few people have told me I find odd things beautiful. Well, consistent with that character trait, here’s a colossal generalization about software development that I find beautiful.

“Programming is about establishing invariants, perturbing them, and then re-establishing them. It is a game of stepping-stone from one island of consistency to another.”The Old New Thing

First off, this is a beautiful way of expressing what’s going on code. I like the echo of musical harmony, where you start at rest, then build tension, then release. I like the stepping-stone metaphor; you’re “in the air” and “unsupported” while you’re jumping from one consistent state to another. I like that it hints towards the difference between the code humans are capable of writing (and reading), and imaginable but currently not-feasible automatically generated systems, in which the invariants (stepping stones) are many and tiny, and of complicated shape; I have this intuition that there’s no reason other than maintainability-by-humans to hold design ideals of “define few invariants” and “define invariants that can be simply expressed”.

The more I think about it, though, the first sentence doesn’t match reality. Is “perturbing” an invariant similar to “violating” it? I guess not, since an invariant is a truth that holds universally over your model.

Letting go of your ideals

Imagine you have a model consisting of two variables, a and b, and an invariant that says “a + b = 0 at all times”.

If a starts out as –1, and b starts as +1; our invariant is satisfied. Assuming we can’t atomically modify both a and b in a single operation, we can’t change either a or b without violating the invariant. Even if the target state for the overall model satisfies the invariant (say a = –2, b = +2), there’s no sequence of operations we can apply without breaking the invariant on the way.

So we’re stuck; we have to weaken the invariant. Instead of preserving “a + b = 0”, we just preserve “a + b = 0 so long as the reader is the sole holder of a lock that governs read and write access”, say.

With this new, weaker invariant, we can take the read/write lock over a and b and make modifications, and then release the lock with a + b = 0, without ever having violated the invariant.

The new weak invariant hasn’t been violated. Has it been “perturbed”? No. At least, not on any interpretation I can come up with.

So where are we? We have the “ideal” invariant (which Raymond’s talking about):

  • a + b = 0

And the “pragmatic” invariant (weakened so that we can actually mutate our model):

  • a + b = 0 if you hold the lock.

Under this interpretation, of course it’s okay to violate (“perturb”, in Raymond’s terminology) the ideal invariant, since it’s just a convenient simplification to sit in a coder’s mental model. The real invariant is the weakened, pragmatic invariant, and it, by definition, is never violated.

Some coders work as if the ideal invariants actually hold

In the real world, probably the majority of coders I run into are of what I’d call the pragmatic-productive style. This style of coder tries approaches serially until something seems to work, and then, bang, moves on to the next business problem that needs solving.

Many (certainly not all) coders who work this way don’t “waste time” thinking about “pragmatic” invariants (e.g. “I need the lock if I want a consistent read of a and b”).

As a result, they write code that works under a single-threaded regime breaks horribly in multi-threaded land. I’m not talking about the incredibly difficult-to-eliminate “thread-safe code is almost impossible for humans to write” threading bugs, I’m talking about the trivial “this was never going to work from the moment two requests arrived at the web server within a second of each other” threading bugs.

There’s a lot of education/evangelism floating around geared towards educating this style of coder to embrace concurrency in a way that will produce code that works, as far as possible.

Some coders work as if invariants don’t matter at all

My bigger concern is that many coders don’t really think in terms of invariants much at all.

They’ll know that each row in your OrderLine table has to belong to a row in the Order table, sure.

But they won’t be able to explain what consistency rules they’re applying to the OrderLineHistory temporal table (with effective start date and effective end date) which they just created and populated. These consistency rules are invariants, and no-one can consume (read) the model without making assumptions about those invariants. It’s the responsibility of the designer to determine those invariants, and set about satisfying them in the code that’s written, communicating them to the people who depend upon the model, and enforcing them wherever feasible.

But, as I say, pragmatic-productive coders tend not to be very interested in this stuff.

As a tangent, invariants are great assertion-fodder, and it can be nice when writing unit tests to also implement a quick re-check of any assertions that have no framework-provided safety-net. This consistency check can be run after each test to verify that in addition to any directly expected behaviour your test was written to assert, the code under test doesn’t result in an inconsistent model.

They may or may not be smited. Smoten? Smitten?

Anyway, the result of ignoring invariants is systems that are difficult to describe, reason about, implement, test, and maintain. If you can’t tell me what invariants hold over the model you just designed, then you haven’t actually designed a model yet. And code that’s built to manipulate a model whose invariants haven’t been thought through will be a super-happy-fun-time fountain of bugs, keeping everybody entertained all the way up to a delayed acceptance test.

And that’s why pragmatic-productive coders, who are all about the time-to-feature and delivering-business-value (neither of which is bad in itself) should care about invariants: because ignoring them increases time-to-feature and delays delivery of business value.

Tags:

I’m very proud to bring you what I’m calling the internet’s first “computer rendered Mandelbrot set-based image thing”

by acha11 13. November 2009 04:11

I guess this is the nerd equivalent to carrying baby photos around and producing them without any provocation, but…

Awwwww, look at the Mandelbrot set my program rendered! Look at its little chubby cheeks and pointy seahorse valleys!

 2

Look, I know that some modern techno-hippie dance-types do take their love of fractals to unnerving extremes, but in their defence: the Mandelbrot set is some seriously profound shit. Up on the screen, it stills even the roaring, gibbering horror and stinging shame of my kludgy implementation. It transcends the hack. My implementation’s glacially slow, but that just serves to build anticipation.

My dad coded a Mandelbrot set renderer some time in the early 90’s with Turbo C on our Amstrad PC1512. The thing had CGA graphics, according to the letter of the standard, but it did have a titillatingly taboo 16 color, high-res mode that was an extension to the standard.

I say “high-res”, but I’m somewhat deflated to report that it was actually 640 x 200 (wikipedia).

The point I’m making is this: the Mandelbrot set was still an amazing thing to see back then, in 16-color 640 x 200, after running overnight.

For a while, in fact, there was talk of getting an 8087 floating point co-processor unit, to speed up those overnight runs.

Here are some things I’d like to see:

  • A generalisation of the Mandelbrot set to higher dimensions. Maybe there’s one already?
    • To be honest, I knew about this in advance; it inspired me to do my own 2d renderer.
  • A GPU-based Mandelbrot zoomer/explorer. Maybe there’s one already?
    • This one I didn’t know about, and I’m a little disappointed; I thought for a moment I’d come up with a great idea.
  • A retro fractal rendering movement, targeting only antique hardware, but generating images of the highest possible precision. Maybe there’s one already? Google hasn’t found me anything yet.
    • Yeah! Niche of one!

Oh, and if you enjoy fractals and procedural generation in general, you might enjoy dmytry’s blog Mostly Polynomial.

Tags:

iStatistician 3.0 is out!

by acha11 10. November 2009 16:56

This release updates iStatistician again to handle iRacing’s November release website changes.

Go get the new version here!

Tags:

Bing cashback - Microsoft falls back on security through obscurity, breaks chair, keeps falling

by acha11 7. November 2009 17:01

Background

Bountii.com wrote a blog post which described (and demonstrated) some fairly half-assed security design in Microsoft’s Bing cashback system. I’d link you to it, but it’s now been taken down by the author at the request of Microsoft’s lawyers.

The class of problem we’re talking about

At its core, this is a case of what I’d call trusted-client syndrome.

As an example, imagine company A, company B, and a customer are involved in a transaction. Company A and company B need to exchange some info as part of the transaction, but it’s a real hassle (in 2009!) to integrate their systems directly. I mean, jeez, we’ve already built a customer-facing website, now we gotta build some B2B web services too?

So, to avoid the technical challenge of directly integrating company A and company B’s systems, company A passes transaction info indirectly to company B, via the customer’s browser.

Here’s the problem: as the info passes through the customer’s machine, it can be modified by the customer or by trojan software running on the client machine, allowing a range of attacks to be launched.

Why Microsoft’s position is inconsistent

The problem is this: MS implemented a dodgy design when MS itself believes it’s dodgy.

Over time, I’ve become a little (a little) more open to the school of thought that says “an occasional security hole is okay if the risk of exposure is low; after all, with usual reconciliation business processes, we’ll detect attackers down the track”.

  1. Let’s just ignore the implicit assumption that our knowledge of the system is perfect, and that there are no secondary vulnerabilities which would allow an attacker to cover tracks to work around the reconciliation processes.
  2. Also, assume that the people doing the reconciliation processes will keep running them :-)  (“hey, why bother recalculating all these per-vendor totals and matching them against our records? The computer already did that for us!” “Awesome. Let’s go to lunch.” “I was just thinking that.” “Me too.” “Hold me.”)

The crux of my argument is this: MS can’t justify this design on “low exposure, high chance of detection” grounds on the one hand, and then also believe it’s worth expunging any mention of the flaw from the internet. Which is it? Acceptable risk or dangerous security flaw? Do you have processes in place to catch discrepancies caused by this vulnerability or not? (Hint: the original bountii post seemed to indicate that the answer is “no”).

The whole thing’s demoralising because it all feels so 2001-ish; I was beginning to hope we were past this kind of crap as a profession. At least the billion-dollar corporate parts of the profession, anyway.

Here’s hoping that this is just a Bing-specific attitude of “time-to-market is more important than that over-engineering approach the Windows and Office nerds take. We’ve got a google to compete with.”

Tags:

iRacing disables 3rd-party extensions

by acha11 28. October 2009 03:30

iRacing released a quarterly update today. Aside from the release of Mosport, one of my favourite tracks from the Grand Prix Legends days, there’s a bunch of stuff to do with hosted racing, and a quick note as follows:

Security
Unverifiable third party replacements of system DLLs (including D3D9.DLL and DINPUT8.DLL) utilized by the simulator will now result in loading errors. If you encounter a Loading Error #66, please remove any third party replacements of D3D9.DLL, DINPUT8.DLL or other imposter system DLLs from your iRacing installation. SoftTH is an allowed dll.

By the sounds of it, this’ll break the Telemetry HUD Plugin I blogged about previously. I think the Telemetry HUD always pushed the boundaries of what’s “fair”, but hey, that whole dynamic’s just part of motorsport.

From my old post:

I’m really surprised that iRacing, an online multiplayer game (where you’d expect some cheat/hack countermeasures on the part of the developers), doesn’t have parasite detection code that picks up either unrecognised or suspicious-looking DLLs, or at least funky stuff like “hey, wait a sec, I have TWO d3d9.dlls loaded in my process space! uncool!”.

Well, I guess I’m happy to no longer be surprised.

I’m interested to see what happens next.  Security arms race ? (warning! hot duck oviduct & phallus-related blog post on the other side of that link). Plugin user revolt? (There’ve already been a few tantrums) Crickets chirping?

Tags:

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

RecentComments

Comment RSS