Another chapter in the never-ending AppDomain security saga.
If a computer goes to sleep while SourceGen is running with a project
open, life gets confusing when the system wakes up. The keep-alive
timer fires and a ping is sent to the remote AppDomain, successfully.
At the same time, the lease expires on the remote side, and the objects
are discarded (apparently without bothering to query the ILease object).
This failure mode is 100% repeatable.
Since we can't prevent sandbox objects from disappearing, we have to
detect and recover from the problem. Fortunately we don't keep any
necessary state on the plugin side, so we can just tear the whole
thing down and recreate it.
The various methods in ScriptManager now do a "health check" before
making calls into the plugin AppDomain. If the ping attempt fails,
the AppDomain is "rebooted" by destroying it and creating a new one,
reloading all plugins that were in there before. The plugin binaries
*should* still be in the PluginDllCache directory since the ping failure
was due to objects being discarded, not AppDomain shutdown, and Windows
doesn't let you mess with files that hold executable code.
A new "reboot security sandbox" option has been added to the DEBUG
menu to facilitate testing.
The PluginManager's Ping() method gets called more often, but not to
the extent that performance will be affected.
This change also adds a finalizer to DisasmProject, since we're relying
on it to shut down the ScriptManager, and it's relying on callers to
invoke its cleanup function. The finalizer throws an assertion if the
cleanup function doesn't get called.
(Issue #82)
The VisParamDescrs specify a type and a default value. If the value
has the wrong type, things would blow up in the editor. We now
check the type at plugin load time, and refuse to load the plugin at
all if an entry has a bad type.
The visualization editor was retaining an IPlugin reference for the
visualization generator selection combo box. After 5 minutes the
proxy object timed out, so if you left the editor open and inactive
for that long you'd start getting weird errors.
We now keep the script identifier string and use that to get a
fresh IPlugin proxy object.
Implemented Apple II hi-res bitmap conversion. Supports B&W and
color. Uses essentially the same algorithm as CiderPress.
Experimented with displaying non-text items in ListView. I assumed
it would work, since it's the sort of thing WPF is designed to do,
but it's always wise to approach with caution. Visualization Sets
now show a 64x64 button as a placeholder for the eventual thumbnail.
Some things were being flaky, which turned out to be because I
wasn't Prepare()ing the plugins before using them from Edit
Visualization. To make this a deterministic failure I added an
Unprepare() call that tells the plugin that we're all done.
NOTE: this breaks all existing plugins.
Got parameter in/out working in EditVisualization dialog. Did some
rearranging in PluginCommon interfaces and data structures. Still
doesn't do anything useful.
Basic infrastructure for taking a list of parameters from a plugin
and turning it into a collection of UI controls, merging in values
from a Visualization object. Doesn't yet do anything useful.
WPF makes the hard things easy and the easy things hard. This was
a hard thing, so it was easy to do (with some helpful sample code).
Yay WPF?
Continue development of non-unique labels. The actual labels are
still unique, because we append a uniquifier tag, which gets added
and removed behind the scenes. We're currently using the six-digit
hex file offset because this is only used for internal address
symbols.
The label editor and most of the formatters have been updated. We
can't yet assemble code that includes non-unique labels, but older
stuff hasn't been broken.
This removes the "disable label localization" property, since that's
fundamentally incompatible with what we're doing, and adds a non-
unique label prefix setting so you can put '@' or ':' in front of
your should-be-local labels.
Also, fixed a field name typo.
We were failing to update properly when a label changed if the label
was one that a plugin cared about. The problem is that a label
add/remove operation skips the code analysis, and a label edit skips
everything but the display update. Plugins only run during the code
analysis pass, so changes weren't being reflected in the display
list until something caused it to refresh.
The solution is to ask the plugin if the label being changed is one
that it cares about. This allows the plugin to use the same
wildcard-match logic that it uses elsewhere.
For efficiency, and to reduce clutter in plugins that don't care
about symbols, a new interface class has been created to handle the
"here are the symbols" call and the "do you care about this label"
call.
The program in Examples/Scripts has been updated to show a very
simple single-call plugin and a slightly more complex multi-call
plugin.
The current AddressMap is now passed into the plugin manager, which
wraps it in an AddressTranslate object and passes that to the
plugins at Prepare() time. This allows plugins to convert addresses
to offsets, making it possible to format complex structures.
This breaks existing plugins.
We were providing platform symbols to plugins through the PlatSym
list, which allowed them to find constants and well-known addresses.
We now pass all project symbols and user labels in as well. The
name "PlatSym" is no longer accurate, so the class has been renamed.
Also, added a bunch of things to the problem list viewer, and
added some more info to the Info panel.
Also, added a minor test to 2011-hinting that does not affect the
output (which is the point).
The plugin objects are MarshalByRefObject stubs, which means they
don't actually implement the interfaces we're checking for. There's
some additional overhead to do the interface check. We can avoid
it by doing the interface queries during initialization, and just
checking some bit flags later on.
Also, in the extension script info window, show a list of
implemented interfaces.