Ryder
Ryder copied to clipboard
"methods whose bodies are too close to one another"?
I have a project where I am patching a bug in the WPF TreeView class by replacing one of its non-public methods with my own implementation. I am installing this "shim" with the following code:
public static void Install()
{
var realMethod = typeof(System.Windows.Controls.TreeView).GetMethod("HandleMouseButtonDown", BindingFlags.Instance | BindingFlags.NonPublic);
var replacementMethod = typeof(TreeViewShim).GetMethod(nameof(TreeView_HandleMouseButtonDown_shim), BindingFlags.Static | BindingFlags.NonPublic);
Redirection.Redirect(realMethod, replacementMethod);
}
This has been working fine on a variety of workstations for several months, but a co-worker's machine just the other day started throwing this exception:
if ((sizeOfPtr == sizeof(long) && difference < 13) || (sizeOfPtr == sizeof(int) && difference < 7))
throw new InvalidOperationException("Unable to redirect methods whose bodies are too close to one another.");
https://github.com/6A/Ryder/blob/master/Ryder.Lightweight/Ryder.Lightweight.cs#L61
To get things working for now, I am going to try a bit of an ugly work-around: I will make two identical copies of my shim method, and if one of them is too close, then in theory it should be impossible for the other one to also be too close (even if it is a trampoline). But, I'm trying to understand why:
a) this works fine on many other machines,
b) it just stopped working on this particular machine where it was working before, and
c) how methods in different classes can have entrypoints less than 13 bytes apart.
What is the correct fix in this situation??
Update: The work-around did not succeed. Will try to gather further information.
A further update: After restarting Windows, the problem went away. The person who observed the bug is pretty sure that this happened once before, as well -- a reboot fixed it, but then it recurred.
Mhm, all this is very strange. Furthermore, I've only ever observed errors due to close method bodies on methods of a same class. I'll look into it.
Do you use the lightweight version (or the full version, if you don't mind recompiling it)? If so, can you try moving these lines below those ones?
I suspect none of the methods have been jitted yet, and thus point to temporary memory locations that might be close to one another.
Alternatively, you can try invoking your TreeView_HandleMouseButtonDown_shim
method before creating the redirection, which will force its compilation (you can provide invalid arguments and make it throw, that's fine).
I will try all those things if/when the problem recurs. As of right now, rebooting the system apparently fixed it, but my coworker will definitely reach out to me if it starts happening again. I also made a test application for him to run that fully annotates all values and the logic flow within the Redirection.Redirect
method, so we're well equipped for when we see the problem again.
Okay, so hopefully we get to the bottom of this. But this kind of behavior makes me wonder how exactly I have control over it...