* Inside Mercutio(pdf)
* Licensing Description
* Software License(pdf)
Understanding the Mercutio-GDevice Problem
Note: this page is changing frequently; you can use NetMind to receive e-mail notification when a new version of the page becomes available.
Description: A Two-Stage BugWhen displaying popup menus, Mercutio uses a function called GetMenuScreen to determine what screen the menu should appear on. In the process of walking the GDevice list, Mercutio locks, then unlocks the GDevice handles (GDHandles). This leaves the GDHandles unlocked.
According to Jim Reekes at Apple who initially tracked down the source of this problem (thanks Jim!), many parts of QuickDraw expect the GDHandles to be locked and dereference them without verifying this first:
The bug is in the PowerPC version of StdText() which has been shipping since the first PowerPC release. It deferences the device handle, and then makes a call that can move memory. Thus the pointer is now invalid... In fact, it appears that QuickDraw, video drivers, and the cursor code all assume the device handles are locked. The cursor code runs at interrupt level, so devices _must_ be locked at all times.Thus, it seems that GDHandles are different than other handles in that they should never be unlocked. This is not currently documented in Inside Macintosh or elsewhere; hopefully a TechNote will be forthcoming.
12/18/97: Apple has released a Technote that addresses this issue: http://devworld.apple.com/technotes/tn/tn1118.html
What applications are affected?Any application can cause this problem if it unlocks GDHandles. We have confirmed that other non-Mercutio-using applications that exhibit this behavior, as well as portions of Apple's own system software (!).
In the Mercutio MDEF, this code is part of the GetMenuScreen routine used to display popup menus. Therefore, we believe that although the Mercutio-portion of this bug is present in all versions of Mercutio up to and including 1.3.4, the bug only occurs in applications that use Mercutio to display popup menus and only if the user displays one of the popup menus. For example, initial investigation shows that BBEdit, which uses the System MDEF for popup menus, does not exhibit the bug.
You can see the buggy code and how it has been fixed in subsequent releases on the GetMenuScreen page.
SymptomsBecause the crash only happens whem memory gets moved under certain conditions, the crash does not always occur, and does not necessarily occur when the problematic code is executed (i.e. a user displays a Mercutio popup menu). Following the above example, BBEdit may crash because another application previously left the GDHandles unlocked.
However, we do observe the following:
SolutionsBecause the problem has two components, it needs to be solved in two parts.
Addressing the problem with MercutioAn obvious solution is to fix the problem in Mercutio, ship a new version, and have developers upgrade their applications. The forthcoming Mercutio 1.5 fixes the problem; a beta is available now (see below).
The list of Mercutio developers is too great to expect everyone to update and get a fix to their users. Even for those who do upgrade, it will take time to get the upgrades to the users, and not all users will upgrade. A system-level solution is needed as well.
Addressing the problem with the OSThe problem can be solved by patching the OS with an INIT or a change to the system software. Based on the following alternatives, it looks like patching HUnlock is the best option:
Available Fixes and PatchesIt is too early to tell whether these patches provide a robust solution so to the problem, use them at your own risk. I suggest trying MercutioGetNextDevicePatch first because it is smaller and will have less of an impact on your system.
Writing a Patcher / Updater ApplicationSeveral people have suggested writing an updater application that scans the user's hard drive to find applications that use Mercutio. The updater would then either install a new, safe version of Mercutio, or NOP-out the problematic code. Aside from the challenge of writing an updater that can recognize and change the various versions of Mercutio that are in use, this approach suffers from the following drawbacks:
Thanks!Thanks to everyone who has helped track down this problem and provided constructive advice on how to solve it.
This site was built on a Macintosh using BBEdit and CometPage.