For some time now, I've observed an intermittent COM problem in my VSIX package for Visual Studio 2010. Attempting to subscribe to one of the IDE's COM-based event sinks randomly throws the following error:
"COM object that has been separated from its underlying RCW cannot be used"
A repro case boils down to this code (which must be used in VSIX, obviously):
using System;
using EnvDTE;
using EnvDTE80;
class Test
{
private readonly Events _events;
private readonly Events2 _events2;
private readonly BuildEvents _buildEvents;
private readonly ProjectItemsEvents _projectItemsEvents;
public Test(IServiceProvider provider)
{
var dte = (DTE)provider.GetService(typeof(DTE));
var dte2 = (DTE2)dte;
// Store all references in fields as a GC precaution.
_events = dte.Events;
_events2 = (Events2)dte2.Events;
_buildEvents = _events.BuildEvents;
_projectItemsEvents = _events2.ProjectItemsEvents;
// Proceed to subscribe to event sinks.
_buildEvents.OnBuildBegin += BuildBeginHandler; // BOOM!
_projectItemsEvents.ItemAdded += ItemAddedHandler;
}
private void ItemAddedHandler(ProjectItem projectItem) { }
private void BuildBeginHandler(vsBuildScope scope, vsBuildAction action) { }
}
I've learned about a possible cause from numerous descriptions of similar problems that can be found on the net. It's basically a side effect of the way Runtime Callable Wrappers and GC interact during COM interop. Here's a link to a similar problem complete with explanation.
I'm fine with that explanation, especially because it suggests an easy workaround - storing the event sink reference in a field in order to prevent it from being prematurely GC'ed. Indeed, many people seem to have solved their problem this way.
What bothers me is that it doesn't work in my case. I'm really stumped as to why. As you can plainly see, I already store all object references in fields as a precaution. Yet the error still occurs. I tried being even more explicit using GC.KeepAlive() calls at the end of the ctor, but to no avail. Is there anything else left to do?
Without a solution, my VSIX randomly fails to load, leaving the user with a single option: to restart Visual Studio and hope it doesn't happen the next time.
Any help will truly be appreciated!
Well, I gave up and simply did the only thing that crossed my mind. I figured that since this is obviously a race condition I can't affect in a predictable manner, I might as well reenter the race if I lose.
So I moved the subscription lines into a while loop that try..catch-es them and retries after a bit of Thread.Sleep(). The loop exits either when both subscriptions succeed or when I've been continuously losing the race for more than 2 seconds.
The kicker is, I haven't lost the race once since I've implemented the change. A true Heisenbug, if I ever saw one.
Anyway, I'm going to stick with this until a proper solution occurs to me or the bug reappears.
I suspect that your problem is really that you are attempting to wire up your event handlers too soon. You normally need to be doing these sorts of things in the Initialize method of your package / toolwindow / whatever - generally speaking if you need to use a service you need to do if after the Initialize method has been called, definitely don't do this in the constructor of your Package.
(This is just a hunch - your Test class doesn't implement any VSX interfaces and so I can't see from your sample when the constructor is being called)
Related
probably a stupid question, but: Is there any way to reliable apply changes to a Roslyn workspace concurrently? And if not, what is the best practice to ensure it's done in correct order?
Example: Say you have some solution loaded into a Workspace, and have a basic function that will add a new project to the solution:
private Workspace _workspace;
// This is not thread-safe, right?
void AddProject()
{
var project = _workspace.CurrentSolution.AddProject(/* ... */);
_workspace.TryApplyChanges(project.Solution);
}
First question: Correct me if wrong, but I think AddProject would not be thread-safe, is that correct?
For example, lets say you want to add to new projects concurrently. So you call AddProject() twice concurrently.
My understanding is there is a race condition, and you might end up with both projects added (if one of the calls completes TryApplyChanges before the other call reaches _workspace.CurrentSolution), or only one of the projects added (if both calls have reached _worksapce.CurrentSolution before either has executed TryApplyChanges).
Second question: If my understanding is correct, then is there any best way to avoid these concurrency issues? I suppose the only real way would be to schedule/execute each modification sequentually, right?
How does Visual Studio, for example, do this.. Are modifications to the Workspace e.g. only done on the Dispatcher?
Thanks
The underlying code is thread-safe, but your usage is not.
TryApplyChanges() will return false if the solution changed in the meantime. If that happens, you need to try the changes again (starting from the new CurrentSolution).
Basically, you need to write
Solution changed;
do {
changed = _workspace.CurrentSolution....();
} while (!_workspace.TryApplyChanges(changed);
This is called a compare-and-swap loop; see my blog for more details.
So I'm working on this application that was developed by other people that are not involved with the project anymore. As stated in the title there are a few thread.sleep() calls that have me scratching my head. I have no experience working with AD.
The worst offender is the following one with a 50 second sleep in a class that inherits Principle.
public class Computer:ComputerPrinciple
{
...
public void MoveToOu(string ou)
{
var userObject = (DirectoryEntry)GetUnderlyingObject();
var newParentOu = new DirectoryEntry("LDAP://" + ou);
userObject.MoveTo(newParentOu);
Thread.Sleep(50000);
userObject.Close();
newParentOu.Close();
}
...
}
There is nothing that explains the reason but I suspect it was an issue with the page refreshing before the changes were fully committed (?). One thing I'm pretty sure of is that Thread.Sleep(50000) is not the correct solution to whatever problem they we're having.
I'd like to hear from people who have experience with this if there is indeed some sort of issue that this would "fix" and what would be the incorporate solution.
Also I'm thinking I should use the "using" directive but I'm wondering about disposing the UnderlyingObject or even just closing it because this code is called from something like this where computer is the principle in witch the move code is
computer.UpdateComputerDescription(collection);
computer.UpdateComputerOu(collection); <--- offending MoveToOu method is called in here
computer.UpdateComputerIsActivedProperty(collection);
computer.Save();
Would closing or disposing of the underlyingObject have a side effect on the methods after that call?
Any input would be welcome.
This use of Thread.Sleep is likely a workaround for not calling CommitChanges.
From documentation
If UsePropertyCache is true, call the CommitChanges method on the new object to make the move permanent
It looks like they were waiting for the cache to flush using an empirical delay.
Second, wrapping any IDisposable you create inside MoveToOu in using will not break anything. It is the correct way to go. Objects used, but not created, inside MoveToOu scope should not be disposed here, but rather be left to the container class dispose mechanism.
I have stumbled across a situation where garbage collection seems to be behaving differently between the same code running written as a Unit Test vs written in the Main method of a Console Application. I am wondering the reason behind this difference.
In this situation, a co-worker and I were in disagreement over the effects of registering an event handler on garbage collection. I thought that a demonstration would be better accepted than simply sending him a link to a highly rated SO answer. As such I wrote a simple demonstration as a unit test.
My unit test showed things worked as I said they should. However, my coworker wrote a console application that showed things working his way, which meant that GC was not occurring as I expected on the local objects in the Main method. I was able to reproduce the behavior he saw simply by moving the code from my test into the Main method of a Console Application project.
What I would like to know is why GC does not seem to collecting objects as expected when running in the Main method of a Console Application. By extracting methods so that the call to GC.Collect and the object going out of scope occurred in different methods, the expected behavior was restored.
These are the objects I used to define my test. There is simply an object with an event and an object providing a suitable method for an event handler. Both have finalizers setting a global variable so that you can tell when they have been collected.
private static string Log;
public const string EventedObjectDisposed = "EventedObject disposed";
public const string HandlingObjectDisposed = "HandlingObject disposed";
private class EventedObject
{
public event Action DoIt;
~EventedObject()
{
Log = EventedObjectDisposed;
}
protected virtual void OnDoIt()
{
Action handler = DoIt;
if (handler != null) handler();
}
}
private class HandlingObject
{
~HandlingObject()
{
Log = HandlingObjectDisposed;
}
public void Yeah()
{
}
}
This is my test (NUnit), which passes:
[Test]
public void TestReference()
{
{
HandlingObject subscriber = new HandlingObject();
{
{
EventedObject publisher = new EventedObject();
publisher.DoIt += subscriber.Yeah;
}
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
Thread.MemoryBarrier();
Assert.That(Log, Is.EqualTo(EventedObjectDisposed));
}
//Assertion needed for foo reference, else optimization causes it to already be collected.
Assert.IsNotNull(subscriber);
}
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
Thread.MemoryBarrier();
Assert.That(Log, Is.EqualTo(HandlingObjectDisposed));
}
I pasted the body above in to the Main method of a new console application, and converted the Assert calls to Trace.Assert invocations. Both equality asserts fail then fail. Code of resulting Main method is here if you want it.
I do recognize that when GC occurs should be treated as non-deterministic and that generally an application should not be concerning itself with when exactly it occurs.
In all cases the code was compiled in Release mode and targeting .NET 4.5.
Edit: Other things I tried
Making the test method static since NUnit supports that; test still worked.
I also tried extracting the whole Main method into an instance method on program and calling that. Both asserts still failed.
Attributing Main with [STAThread] or [MTAThread] in case this made a difference. Both asserts still failed.
Based on #Moo-Juice's suggestions:
I referenced NUnit to the Console app so that I could use the NUnit asserts, they failed.
I tried various changes to visibility to the both the test, test's class, Main method, and the class containing the Main method static. No change.
I tried making the Test class static and the class containing the Main method static. No change.
If the following code was extracted to a separate method, the test would be more likely to behave as you expected. Edit: Note that the wording of the C# language specification does not require this test to pass, even if you extract the code to a separate method.
{
EventedObject publisher = new EventedObject();
publisher.DoIt += subscriber.Yeah;
}
The specification allows but does not require that publisher be eligible for GC immediately at the end of this block, so you should not write code in such a way that you are assuming it can be collected here.
Edit: from ECMA-334 (C# language specification) §10.9 Automatic memory management (emphasis mine)
If no part of the object can be accessed by any possible continuation of execution, other than the running of finalizers, the object is considered no longer in use and it becomes eligible for finalization. [Note: Implementations might choose to analyze code to determine which references to an object can be used in the future. For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, an implementation might (but is not required to) treat the object as no longer in use. end note]
The problem isn't that it's a console application - the problem is that you're likely running it through Visual Studio - with a debugger attached! And/or you're compiling the console app as a Debug build.
Make sure you're compiling a Release build. Then go to Debug -> Start Without Debugging, or press Ctrl+F5, or run your console application from a command line. The Garbage Collector should now behave as expected.
This is also why Eric Lippert reminds you not to run any perf benchmarks in a debugger in C# Performance Benchmark Mistakes, Part One.
The jit compiler knows that a debugger is attached, and it deliberately de-optimizes the code it generates to make it easier to debug. The garbage collector knows that a debugger is attached; it works with the jit compiler to ensure that memory is cleaned up less aggressively, which can greatly affect performance in some scenarios.
Lots of the reminders in Eric's series of articles apply to your scenario. If you're interested in reading more, here are the links for parts two, three and four.
I am attempting to build (for learning purposes) my own event logger; I am not interested in hearing about using a non-.net frameworks instead of building my own as I am doing this to better understand .net.
The idea is to have an event system that I can write out to a log file and/or pull from while inside the program. To do this I am creating an LogEvent class that will be stored inside of a Queue<LogEvent>.
I am planning on using the following fields in my LogEvent class:
private EventLogEntryType _eventType //enum: error, info, warning...
private string _eventMessage
private Exception _exception
private DateTime _eventTime
What I am not sure is the best way to capture the object that caused the event to be called. I thought about just doing a private Object _eventObject; but I am thinking that is not thread safe or secure.
Any advice on how to best store the object that called the event would be appreciated. I am also open to any other suggestions you may have.
Thanks, Tony
First off, nothing wrong with writing your own. There are some good frameworks our there, but sometimes you reach the point where some bizarre requirement gets you rolling your own, I've been there anyway...
I don't think you should be using text messages. After doing this type of logging in several projects, I have come the the conclusion that the best approach is to have a set of event types (integer IDs) with some type of extra information field.
You should have an enum of LogEvetTypes that looks something like this:
public enum LogEventTypes
{
//1xxx WS Errors
ThisOrThatWebServiceError = 1001,
//2xxx DB access error
//etc...
}
This, from my experience will make your life much easier when trying to make use of the information you logged. You can also add an ExtraInformation field in order to provide event instance specific information.
As for the object that caused the event, I would just use something like typeof(YourClass).ToString();. If this a custom class you created, you can also implement a ToString override that will name sense in your logging context.
Edit: I am adding several details I wrote about in the comments, since I think they are important. Passing objects, which are not immutable, by ref to service methods is generally not a good idea. You might reassigne the same variable in a loop (for example) and create a bug that is near-impossible to find. Also, I would recommend doing some extra work now to decouple the logging infrastructure from the implementation details of the application, since doing this later will cause a lot of pain. I am saying this from my own very painful experience.
We're dealing with the GC being too quick in a .Net program.
Because we use a class with native resources and we do not call GC.KeepAlive(), the GC collects the object before the Native access ends. As a result the program crashes.
We have exactly the problem as described here:
Does the .NET garbage collector perform predictive analysis of code?
Like so:
{ var img = new ImageWithNativePtr();
IntPtr p = img.GetData();
// DANGER!
ProcessData(p);
}
The point is: The JIT generates information that shows the GC that img is not used at the point when GetData() runs. If a GC-Thread comes at the right time, it collects img and the program crashes. One can solve this by appending GC.KeepAlive(img);
Unfortunately there is already too much code written (at too many places) to rectify the issue easily.
Therefore: Is there for example an Attribute (i.e. for ImageWithNativePtr) to make the JIT behave like in a Debug build? In a Debug build, the variable img will remain valid until the end of the scope ( } ), while in Release it looses validity at the comment DANGER.
To the best of my knowledge there is no way to control jitter's behavior based on what types a method references. You might be able to attribute the method itself, but that won't fill your order. This being so, you should bite the bullet and rewrite the code. GC.KeepAlive is one option. Another is to make GetData return a safe handle which will contain a reference to the object, and have ProcessData accept the handle instead of IntPtr — that's good practice anyway. GC will then keep the safe handle around until the method returns. If most of your code has var instead of IntPtr as in your code fragment, you might even get away without modifying each method.
You have a few options.
(Requires work, more correct) - Implement IDisposable on your ImageWithNativePtr class as it compiles down to try { ... } finally { object.Dispose() }, which will keep the object alive provided you update your code with usings. You can ease the pain of doing this by installing something like CodeRush (even the free Xpress supports this) - which supports creating using blocks.
(Easier, not correct, more complicated build) - Use Post Sharp or Mono.Cecil and create your own attribute. Typically this attribute would cause GC.KeepAlive() to be inserted into these methods.
The CLR has nothing built in for this functionality.
I believe you can emulate what you want with a container that implements IDispose, and a using statement. The using statement allows for defining the scope and you can place anything you want in it that needs to be alive over that scope. This can be a helpful mechanism if you have no control over the implementation of ImageWithNativePtr.
The container of things to dispose is a useful idiom. Particularly when you really should be disposing of something ... which is probably the case with an image.
using(var keepAliveContainer = new KeepAliveContainer())
{
var img = new ImageWithNativePtr();
keepAliveContainer.Add(img);
IntPtr p = img.GetData();
ProcessData(p);
// anything added to the container is still referenced here.
}