"Side By Side Assemblies" Bring DLL Hell 2.0
neutrino38 writes "This is an alert for all developers using Microsoft Visual Studio 2005. At the beginning of January, Microsoft issued a security fix for Visual Studio 2005 forcing the use of new dynamic libraries (DLLs) by all applications compiled with this IDE. Basically, applications compiled with Visual Studio 2005 will not work anymore on an ordinary (non-dev) PC unless the newer DLLs are installed. And we found out that this is true on fully updated PCs. I just posted some details and some suggested fixes." Read below for some more background on Microsoft's so-called "side by side assemblies."
For those unfamiliar with the Microsoft world, native microsoft applications written in C++ rely on dynamic libraries. Two of them are infamous: MSVCRT.DLL and MFCxx.dll. Because of software evolution and security fixes, multiple versions of these DLLs were often present in the system, causing application instability. Where Linux implemented a simple suffix notation on the dynamic libraries, Microsoft created a new beast in 2001: the Side By Side assembly. These are basically DLLs with a companion XML file that identifies them. The XML file contains a digital signature and when the system binds these DLLs dynamically to an application, it checks that the signature of the DLL matches the DLL itself. When everythings runs well, this is pretty transparent. But when issues arise, it becomes excruciatingly difficult to troubleshoot and fix. DLL hell is not over.
For those unfamiliar with the Microsoft world, native microsoft applications written in C++ rely on dynamic libraries. Two of them are infamous: MSVCRT.DLL and MFCxx.dll. Because of software evolution and security fixes, multiple versions of these DLLs were often present in the system, causing application instability. Where Linux implemented a simple suffix notation on the dynamic libraries, Microsoft created a new beast in 2001: the Side By Side assembly. These are basically DLLs with a companion XML file that identifies them. The XML file contains a digital signature and when the system binds these DLLs dynamically to an application, it checks that the signature of the DLL matches the DLL itself. When everythings runs well, this is pretty transparent. But when issues arise, it becomes excruciatingly difficult to troubleshoot and fix. DLL hell is not over.
What might be interesting to note here is that the summary isn't everything there is to side-by-side (SxS) assemblies.
Suppose you're building an application using two DLLs, let's call them A and B. Both depend on a third DLL named C. Now, suppose A uses C version X, and B uses C version Y. You're screwed, right? Not with SxS, since that allows multiple versions of C to be loaded. That's the real added value of SxS.
All this is in theory of course, which as we all know is in theory equal to practice, but in practice is not...
Error: password can't contain reverse spelling of ancient Chinese emperor
Speaking as a user, can we get statically linked libraries? I don't care if it's dependency hell or DLL hell. I want self-contained applications.
That defeats the whole purpose of a DLL anyway. The thought was that you wouldn't have to "reinvent the wheel" and you could reuse code. However, Microsoft's failure to document their operating system's API thoroughly in a public manner led to developers relying on undocumented features that were later changed. Then, those applications needed older versions of those libraries and would install them over the newer versions. This, of course, crashed the newer applications. Ugh.
Everybody who developes applications for the Windows platform should know that you need to include the merge module for the C/C++ runtime libraries in your installer. You've just been luck so far that other applications have installed the DLL's you needed for you. Try your app the way it is on a clean install of Windows XP without the service packs and see how well that goes :P
In fact the SxS assembly system in windows is the only real way out of DLL hell, much better than the versioning scheme for shared libraries used in Linux. Get your facts straight before posting.
The interactive way to Go -- http://www.playgo.to/iwtg/en/
I upgraded my Fallout 3 installation yesterday. After patching, the game wouldn't run, returning some fairly obtuse message about import ordinals. So I googled the message, and found out it's because the game now links against a newer version of "Microsoft(R) Games for Windows(TM) Live(TM)" whatever. Note that this wasn't some new patch, it's months old and yet this problem, which must realistically be hitting quite a few users, persists. This isn't something you get via Windows Update either, this is just some obscure 'distributable runtime' crap you should know you need?
So let me repeat that: Super mainstream game on a super mainstream platform (Vista x64), no add-ons, I patch to the latest version and it won't start, nothing is mentioned at the developer's site.
Now I recognize good old Bethesda again. Here's how they'd be able to repro: Fully updated Vista machine, install game from DVD, apply patch, notice it won't fucking run.
I don't normally give much for the 'PC-gaming sucks' choir, but c'mon..
Belief is the currency of delusion.
This has been heavily debated in comments in the Visual C++ blog:
http://blogs.msdn.com/vcblog/archive/2009/08/05/active-template-library-atl-security-updates.aspx
Unfortunately, the VC++ team doesn't seem to understand what's wrong with pushing out a critical update through automatic updates that silently updates dependency requirements. I've personally seen projects that were suddenly broken by this update and the ensuing confusion that resulted.
Java?
No, because that's what sxs solves. You can have multiple versions of the MSVCxxx libraries installed and each app can find the correct one.
It's similar to the library versioning that unix does, except instead of changing the filename each library has a manifest containing its version number and a checksum of the library, and the loader knows how to fing the right one.
This is a complete non-story written by someone who doesn't test applications on a clean system prior to distribution, then wonders why it doesn't work.
Yeah SxS works a treat. No more dll hell. Great for servicing too. The problem here is moronic devs not shipping the libraries that they link against. MS would be castigated if they didn't fix security holes. Why oh why does kdawson think this is a return to dll hell? Does he actually know what SxS is? Does he even have experience of windows development?
Writing "managed" code has nothing to do with using sane concurrency abstractions. You can do one without the other. Hell, you can easily write buggy managed code that relies on raw semaphores and deadlocks often, and you can write elegant message-passing C++ code. The key is the abstraction, not the runtime mechanism.
Everyone (even Windows programmers) should read Ulrich Drepper's piece on how to write shared libraries. (Warning: PDF.) (Likewise, even free software developers should read Raymond Chen's blog.)
Oh jesus christ I can't stand how fucking idiotic everything in this discussion is.
What happened: In August, they released a patch to the IDE that required a new version of the shared libraries. Binaries built with this patched version of the IDE/compiler/toolchain will by default require a version of DLLs that aren't installed by default on many systems.
What would have prevented this asshat's blog post: Write a fucking installer that includes the DLLs you use. Thus, when your compiler changes, and your new packages rely on some stuff, magically that 'some stuff' is bundled along with your binary, and everything _still works_. Relying on OTHER packages to have good installers that properly put stuff in to SxS is just idiotic. "Wah, I rely on stuff that I'm specifically told I can't rely on, Microsoft sucks, and SxS is evil!"
No. SxS has been SAVING your ass from updates like this since Windows XP. Surprisingly, you can now NOT recompile your project, and have it still work, even though there's a newer version of DLLs you depend on, because the backwards compatibility problem of these DLLs is just gone. The version YOU want and need and depend on is still there, still usable. Something else on the system that wants the newer version gets it, and all its patched glory. This is actually a security hole, and in THAT case, the DLL you depend on WILL change to fix the security problem. Nothing in the August 2009 update to VS 2005 seems to indicate that this happened, it's only for newly compiled binaries.
So, in summary: The blog poster is an idiot, he hates his user, he's too lazy to write a real installer, he has incompetent developers that don't care about the security of their product, and he asked for help and got 4 completely idiotic responses. Now everyone on slashdot who knows nothing about SxS and the actual problems it causes (and yes there are some) think that it's the same problem we've always had, but worse.
Note: I'm not a Windows developer (Linux developer), and I've not used Windows in well over a year (Mac user). But I've been bitten by SxS in my last job and dealing with VB.Net, back when I didn't know I had to make a real installer for my stuff. I somehow managed to learn to not be an idiot, and the blog poster should too.
Additionally, DLLs can enhance security. If there's a bug in MSVCRT.DLL, Microsoft can patch it and release it as an update. In a static world, every application that had that buggy code compiled into it would have to be rebuilt and redistributed.
In a statically-linked world, every application would need to be rebuilt (on Windows, redistributed) every time an API / ABI change was released, as well as every time a bug was fixed. Furthermore, download sites would either have to release binaries for every API / ABI combination (that's a ton of releases per version) and deal with users downloading the wrong one, or do the open-source model and release the source, forcing the users to build the application on their system and rebuild every API / ABI update. And somehow I don't think the latter solution would fly with the Windows community.
Like other posters have said, Microsoft's solution is actually not a bad one. Allowing multiple DLLs to be loaded simultaneously is not a pretty solution, but it's not a pretty problem that they have to solve, either. Advance with backwards-compatibility in mind as much as it makes sense to, and use SxS DLLs when it doesn't.
Oops. Correct link. (I wish Slashdot would warn about obviously incorrect links.)
This can bite you in a lot of conditions. One of the canonical examples is memory allocation. For example, foo.dll allocates memory and passes the pointer to bar.exe. To operate safely, bar.exe has to pass the pointer back to foo.dll so it can be freed. Otherwise, foo.dll might be using -- say -- malloc() and free() from one version of the C runtime library, and bar.exe might be using malloc() and free() from a different version. Because the different DLLs will end up allocating from different arenas, you'll corrupt both if you malloc() using one and free() using the other.
There's a reasonable argument that passing memory ownership without providing allocation functions is a bad way to design libraries. Unfortunately, some interface standards specify bindings that forbid providing that kind of deallocation function in the DLL. (I'm looking at you, CCSDS SLE! I still haven't forgiven you for inflicting this form of DLL hell upon me so many years ago.)
Blood?
She made the willows dance
But when issues arise, it becomes excruciatingly difficult to troubleshoot and fix.
The version information is written in plain text in the manifest. The files have names based on the version information in the WinSxS folder. If you get the error and notice the files aren't there, its fairly trivial to troubleshoot and fix.
I'm not a fan of side by side assemblies, I just hate to see issues like this blown out of proportion as it obscures some of the real issues that developers face when developing for Windows (such as just about every bug filed on Microsoft Connect being closed as "by design" instead of being worked on or at the very least closed as "can't fix, compatibility issues", for example).
Microsoft did this intentionally. They deprecated the vulnerable version of the dll. You "solution" to the problem of your customers still running the vulnerable version of the VC dlls should be to either force them to upgrade or install the new dlls for them. Instead you decide the security is a hassle and undo the fix on your developer machine, so you can ignore the larger issue that you are building insecure software and you customers are running insecure computers. Fix the problem, instead of whining about it and continuing to crank out crappy .net software. How hard would it be to have your software check for the problem dll versions, and direct the customer to download/install the new version? Cripes, games do it all the time when they check what version of direct x is installed.
You are 100% correct. The "problem" with those guys is that they did not even understand that they have to redistribute CRT DLL with their binaries even before the update. They got lucky there because on most systems, it is already there (I believe Vista has it out of the box, and probably some MS software will install it on XP - maybe even IE7/8?), so they got away with not distributing it. Now the update brought in a newer version of runtime, which of course the clients don't have, and they suddenly realize that they didn't distribute their dependencies properly. What does "DLL Hell" or side by side assemblies even have to do with it?
And, if they find it so hard to comprehend the idea that they have to give users the DLLs they link against, they could always just compile CRT statically and be done with it.
That's a contradiction. Sane people wouldn't write software for windows, rendering this a non-issue.
"It works fine for me" said the MS developer.
I put it down the the decline of Microsoft, I've been working as a MS dev for the past 15+ years, and since Bill left (a coincidence, I feel) the company has started a steady decline - wasting their money on frippery, attempting to get a new growth market, screwing with established systems in place of selling new stuff, and generally trying desperately to get your money off you. At least in the past, they were also focussed on making good technical stuff too.
Hands up anyone who knows what an "activation context" is! If you don't you have no idea what WinSxS does, how it does it or how to diagnose it when it goes wrong.
In my opinion, WinSxS is a good mechanism, or at least as good as Microsoft could have made it while working within the constraints of history. However, WinSxS cannot be used in the real world without properly understanding it, and achieving that understanding is very painful indeed. The MSDN documentation is piecemeal, appears incomplete and inaccurate in a few places and lacks a proper overview. I think the only reason I properly twigged what activation contexts are about is that I had recently written a mechanism that operated on similar principles (a thread-local stack of context-related information).
I wrote a Wiki page at work describing what (I think) WinSxS's motivation is, how it works and some of the problems it suffers from. I'd like to put it somewhere on the public internet - any suggestions? It should ideally be somewhere wiki-like where people can correct its inevitable inaccuracies without me having to maintain it, but I'm not sure it's appropriate for wikipedia.
"The Milliard Gargantubrain? A mere abacus - mention it not."
For those of you who do not know, the parent poster is talking about these topics:
A) A programming language called Brainfuck.
B) Homophobia.
C) How long the parent has known about Brainfuck.
It seems clear to me that there is a language called Brainfuck that everyone needs to be made aware of.
"His name was James Damore."
If you use GlobalAlloc() to allocate the memory, then GlobalFree() always frees it. (I'm quoting from my nightmares here.)
The problem happens in VC++. The new operator eventually calls malloc() which eventually calls GlobalAlloc(), through chains of function calls that are fairly non-obvious, unless you read the disassembly or the source. GlobalAlloc() is a based Windows function, so every DLL links to the same system DLLs. The new and malloc calls are in the Microsoft Visual C++ libraries. Those libraries are loaded on a per DLL/EXE basis. As such, different VC++ DLLs can link to different VC++ run-time libraries, containing identical (or nearly identical) new and malloc functions but with different data areas.
Additionally, malloc() is optimized so it doesn't always call GlobalAlloc() whenever new memory is required. malloc() has it's own list of memory allocations, and that is where the problem is. A malloc() from one DLL with it's own data memory area knows nothing about another DLL's data memory area. As such, the free() call can't possibly succeed when the data was allocated in a different DLL.
Unfortunately, the torture doesn't end there. There are only two ways around the problem. Firstly, you can never pass memory allocations across DLL boundaries. Unfortunately, for some applications this doesn't work, for example COM and ActiveX controls. Alternatively, you can create a new type of memory handler to handle inter-DLL memory allocations. Microsoft created the IMalloc API for this reason. However, it is impossible to make the IMalloc API work across all possible failure modes. Also, IMalloc is not used by default for either new, delete, malloc() or free(). As such, the IMalloc API does not completely solve the inter-DLL issues, and introduces new problems of its own.
The IMalloc API is at the heart of COM, which is also at the heart of C#. Normally, C# might be a good language for soft real-time, long life systems. However, if any bug exists in any control using the IMalloc API, then all of the CLR can become unstable. As such, C# is the home of my biggest programming disaster ever. A program that is less reliable and runs thousands of times slower than the equivalent in C. In C/C++, some freedom exists to properly handle memory allocations, and data types are checked at compile time. In COM, it is almost impossible to understand all of the complexities of all of the memory allocations and data type conversions. As such, it is both easy to make mistakes with COM, and very difficult to work around them.
ActiveX/COM/DLLs are the root source of many serious security and reliability issues inside Windows. Historically, reliability and security issues were at least traceable to an executable. Now, all bets are off. ActiveX is present in Windows Explorer, Office and Internet Explorer, making it very difficult to effectively lock down the system. As such, system requirements for "a solid application" on "Microsoft Windows" represent an oxymoron. The result of these contradictory requirements is the application separation. Big and small applications use web servers running embedded Operating Systems or Linux (printers, Google, Bing), and display the results on a web browser on Windows.
In short, this bug is not a side effect of the Windows Memory Allocation API: GlobalAlloc() and GlobalFree(). It is a side-effect of DLLs under Microsoft Windows, and importantly the C Run-Time Library DLL implementation. As a result of the attempted workarounds, it has probably had as big of an effect on Windows as the old Intel 8088 segmented memory architecture.